Introduce StartRouter to gate first run with onboarding. Persist state in SharedPreferences (onboarded_v1). Add WelcomeScreen, a 3-step OnboardingFlow, and a SignInScreen placeholder with Apple/Google buttons and "coming soon" toasts plus continue as guest. Apply new AppThemes (light/dark, high-contrast option) built from design tokens and wire into MaterialApp (theme/darkTheme, system mode). Add ThemeProvider to persist ThemeMode and high-contrast flags (not yet hooked into the tree). Add EN/MS i18n strings for welcome, onboarding, auth, and CTAs. Include assets/tokens/design-tokens.json for design tooling parity.
62 lines
1.7 KiB
Dart
62 lines
1.7 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:shared_preferences/shared_preferences.dart';
|
|
|
|
/// ThemeProvider manages ThemeMode and High-Contrast flag with persistence.
|
|
class ThemeProvider extends ChangeNotifier {
|
|
static const _kThemeModeKey = 'ui.theme_mode'; // 'system' | 'light' | 'dark'
|
|
static const _kHighContrastKey = 'ui.high_contrast'; // bool
|
|
|
|
ThemeMode _mode = ThemeMode.system;
|
|
bool _highContrast = false;
|
|
|
|
ThemeMode get themeMode => _mode;
|
|
bool get highContrast => _highContrast;
|
|
|
|
Future<void> init() async {
|
|
final prefs = await SharedPreferences.getInstance();
|
|
final modeStr = prefs.getString(_kThemeModeKey) ?? 'system';
|
|
_mode = _decodeMode(modeStr);
|
|
_highContrast = prefs.getBool(_kHighContrastKey) ?? false;
|
|
notifyListeners();
|
|
}
|
|
|
|
Future<void> setThemeMode(ThemeMode mode) async {
|
|
if (_mode == mode) return;
|
|
_mode = mode;
|
|
final prefs = await SharedPreferences.getInstance();
|
|
await prefs.setString(_kThemeModeKey, _encodeMode(mode));
|
|
notifyListeners();
|
|
}
|
|
|
|
Future<void> setHighContrast(bool value) async {
|
|
if (_highContrast == value) return;
|
|
_highContrast = value;
|
|
final prefs = await SharedPreferences.getInstance();
|
|
await prefs.setBool(_kHighContrastKey, value);
|
|
notifyListeners();
|
|
}
|
|
|
|
String _encodeMode(ThemeMode m) {
|
|
switch (m) {
|
|
case ThemeMode.light:
|
|
return 'light';
|
|
case ThemeMode.dark:
|
|
return 'dark';
|
|
case ThemeMode.system:
|
|
default:
|
|
return 'system';
|
|
}
|
|
}
|
|
|
|
ThemeMode _decodeMode(String s) {
|
|
switch (s) {
|
|
case 'light':
|
|
return ThemeMode.light;
|
|
case 'dark':
|
|
return ThemeMode.dark;
|
|
case 'system':
|
|
default:
|
|
return ThemeMode.system;
|
|
}
|
|
}
|
|
} |