Add offline-first mode support to settings

- Add AppMode enum (local, online)
- Extend settings datasource with mode, setup, and onboarding flags
- Update settings viewmodel with mode helpers and persistence
This commit is contained in:
m3mo 2026-02-03 14:20:49 +01:00
parent 3c3da50a54
commit ceef4f4c72
3 changed files with 81 additions and 1 deletions

View File

@ -1,11 +1,19 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
import '../domain/enums/app_mode.dart';
abstract class SettingsLocalDataSource { abstract class SettingsLocalDataSource {
Locale? getLocale(); Locale? getLocale();
Future<void> setLocale(Locale locale); Future<void> setLocale(Locale locale);
ThemeMode getThemeMode(); ThemeMode getThemeMode();
Future<void> setThemeMode(ThemeMode mode); Future<void> setThemeMode(ThemeMode mode);
AppMode? getAppMode();
Future<void> setAppMode(AppMode mode);
bool isSetupCompleted();
Future<void> setSetupCompleted(bool completed);
bool isOnboardingShown();
Future<void> setOnboardingShown(bool shown);
} }
class SettingsLocalDataSourceImpl implements SettingsLocalDataSource { class SettingsLocalDataSourceImpl implements SettingsLocalDataSource {
@ -13,6 +21,9 @@ class SettingsLocalDataSourceImpl implements SettingsLocalDataSource {
static const String _localeKey = 'locale'; static const String _localeKey = 'locale';
static const String _themeModeKey = 'theme_mode'; static const String _themeModeKey = 'theme_mode';
static const String _appModeKey = 'app_mode';
static const String _setupCompletedKey = 'setup_completed';
static const String _onboardingShownKey = 'onboarding_shown';
SettingsLocalDataSourceImpl({required this.sharedPreferences}); SettingsLocalDataSourceImpl({required this.sharedPreferences});
@ -39,4 +50,36 @@ class SettingsLocalDataSourceImpl implements SettingsLocalDataSource {
Future<void> setThemeMode(ThemeMode mode) async { Future<void> setThemeMode(ThemeMode mode) async {
await sharedPreferences.setInt(_themeModeKey, mode.index); await sharedPreferences.setInt(_themeModeKey, mode.index);
} }
@override
AppMode? getAppMode() {
final index = sharedPreferences.getInt(_appModeKey);
if (index == null) return null;
return AppMode.values[index];
}
@override
Future<void> setAppMode(AppMode mode) async {
await sharedPreferences.setInt(_appModeKey, mode.index);
}
@override
bool isSetupCompleted() {
return sharedPreferences.getBool(_setupCompletedKey) ?? false;
}
@override
Future<void> setSetupCompleted(bool completed) async {
await sharedPreferences.setBool(_setupCompletedKey, completed);
}
@override
bool isOnboardingShown() {
return sharedPreferences.getBool(_onboardingShownKey) ?? false;
}
@override
Future<void> setOnboardingShown(bool shown) async {
await sharedPreferences.setBool(_onboardingShownKey, shown);
}
} }

View File

@ -0,0 +1,4 @@
enum AppMode {
local,
online,
}

View File

@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import '../../../../core/logging/app_logger.dart'; import '../../../../core/logging/app_logger.dart';
import '../../data/settings_local_datasource.dart'; import '../../data/settings_local_datasource.dart';
import '../../domain/enums/app_mode.dart';
class SettingsViewModel extends ChangeNotifier { class SettingsViewModel extends ChangeNotifier {
final SettingsLocalDataSource dataSource; final SettingsLocalDataSource dataSource;
@ -16,9 +17,17 @@ class SettingsViewModel extends ChangeNotifier {
Locale? _locale; Locale? _locale;
ThemeMode _themeMode = ThemeMode.system; ThemeMode _themeMode = ThemeMode.system;
AppMode? _appMode;
bool _setupCompleted = false;
bool _onboardingShown = false;
Locale? get locale => _locale; Locale? get locale => _locale;
ThemeMode get themeMode => _themeMode; ThemeMode get themeMode => _themeMode;
AppMode? get appMode => _appMode;
bool get setupCompleted => _setupCompleted;
bool get onboardingShown => _onboardingShown;
bool get isLocalMode => _appMode == AppMode.local;
bool get isOnlineMode => _appMode == AppMode.online;
static const supportedLocales = [ static const supportedLocales = [
Locale('en'), Locale('en'),
@ -28,7 +37,10 @@ class SettingsViewModel extends ChangeNotifier {
void _loadSettings() { void _loadSettings() {
_locale = dataSource.getLocale() ?? const Locale('en'); _locale = dataSource.getLocale() ?? const Locale('en');
_themeMode = dataSource.getThemeMode(); _themeMode = dataSource.getThemeMode();
logger.info('Settings loaded: locale=$_locale, themeMode=$_themeMode'); _appMode = dataSource.getAppMode();
_setupCompleted = dataSource.isSetupCompleted();
_onboardingShown = dataSource.isOnboardingShown();
logger.info('Settings loaded: locale=$_locale, themeMode=$_themeMode, appMode=$_appMode, setupCompleted=$_setupCompleted, onboardingShown=$_onboardingShown');
} }
Future<void> setLocale(Locale locale) async { Future<void> setLocale(Locale locale) async {
@ -45,6 +57,27 @@ class SettingsViewModel extends ChangeNotifier {
notifyListeners(); notifyListeners();
} }
Future<void> setAppMode(AppMode mode) async {
_appMode = mode;
await dataSource.setAppMode(mode);
logger.info('App mode changed to: $mode');
notifyListeners();
}
Future<void> setSetupCompleted(bool completed) async {
_setupCompleted = completed;
await dataSource.setSetupCompleted(completed);
logger.info('Setup completed: $completed');
notifyListeners();
}
Future<void> setOnboardingShown(bool shown) async {
_onboardingShown = shown;
await dataSource.setOnboardingShown(shown);
logger.info('Onboarding shown: $shown');
notifyListeners();
}
String getLanguageName(Locale locale) { String getLanguageName(Locale locale) {
switch (locale.languageCode) { switch (locale.languageCode) {
case 'en': case 'en':