Improve app UX by adding animated transitions for screen switches and introducing a persisted guest onboarding flow. - Add AnimatedSwitcher-based fade+slide transitions for screens and tab switches for smoother navigation. - Persist a 'user_mode' SharedPreferences key and provide guest helpers to mark users as guest and influence routing. - Update SignInScreen continue-as-guest action to set onboarding and guest flags and navigate to MainScreen. - Normalize locales in LocaleProvider to language-only values and persist normalized language codes to ensure compatibility with Flutter localization delegates. - Replace Row with Wrap in ReportCard to improve spacing and responsiveness. No breaking changes
110 lines
3.2 KiB
Dart
110 lines
3.2 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:shared_preferences/shared_preferences.dart';
|
|
import 'i18n.dart';
|
|
|
|
/// Provider for managing app locale and language switching
|
|
class LocaleProvider extends ChangeNotifier {
|
|
static const String _languageKey = 'lang';
|
|
static const String _defaultLanguage = 'en';
|
|
|
|
Locale _locale = const Locale('en');
|
|
late SharedPreferences _prefs;
|
|
|
|
/// Get the current locale
|
|
Locale get locale => _locale;
|
|
|
|
/// Get the current language code
|
|
String get languageCode => _locale.languageCode;
|
|
|
|
/// Initialize the locale provider
|
|
Future<void> init() async {
|
|
_prefs = await SharedPreferences.getInstance();
|
|
final saved = _prefs.getString(_languageKey) ?? _defaultLanguage;
|
|
final parts = saved.split(RegExp(r'[-_]'));
|
|
// Normalize and keep language-only locales so they match Global*Localizations delegates
|
|
final language = parts.isNotEmpty && parts[0].isNotEmpty ? parts[0] : _defaultLanguage;
|
|
_locale = Locale(language);
|
|
await I18n.init(_locale);
|
|
notifyListeners();
|
|
}
|
|
|
|
/// Set the locale and persist the change
|
|
Future<void> setLocale(Locale locale) async {
|
|
// Normalize to language-only locale to ensure compatibility with delegates
|
|
final normalized = Locale(locale.languageCode);
|
|
if (_locale == normalized) return;
|
|
|
|
_locale = normalized;
|
|
final saveValue = _locale.languageCode;
|
|
await _prefs.setString(_languageKey, saveValue);
|
|
await I18n.init(_locale);
|
|
notifyListeners();
|
|
}
|
|
|
|
/// Toggle between English and Bahasa Malaysia
|
|
Future<void> toggleLanguage() async {
|
|
final newLanguage = _locale.languageCode == 'en' ? 'ms' : 'en';
|
|
await setLocale(Locale(newLanguage));
|
|
}
|
|
|
|
/// Set language to English
|
|
Future<void> setEnglish() async {
|
|
await setLocale(const Locale('en'));
|
|
}
|
|
|
|
/// Set language to Bahasa Malaysia
|
|
Future<void> setMalay() async {
|
|
await setLocale(const Locale('ms'));
|
|
}
|
|
|
|
/// Check if current language is English
|
|
bool get isEnglish => _locale.languageCode == 'en';
|
|
|
|
/// Check if current language is Bahasa Malaysia
|
|
bool get isMalay => _locale.languageCode == 'ms';
|
|
|
|
/// Get the display name for the current language
|
|
String get currentLanguageDisplayName {
|
|
switch (_locale.languageCode) {
|
|
case 'en':
|
|
return 'English';
|
|
case 'ms':
|
|
return 'Bahasa Malaysia';
|
|
default:
|
|
return 'English';
|
|
}
|
|
}
|
|
|
|
/// Get the native display name for the current language
|
|
String get currentLanguageNativeName {
|
|
switch (_locale.languageCode) {
|
|
case 'en':
|
|
return 'English';
|
|
case 'ms':
|
|
return 'Bahasa Malaysia';
|
|
default:
|
|
return 'English';
|
|
}
|
|
}
|
|
|
|
/// Get available locales
|
|
List<Locale> get availableLocales => const [
|
|
Locale('en'),
|
|
Locale('ms'),
|
|
];
|
|
|
|
/// Get available language codes
|
|
List<String> get availableLanguageCodes => ['en', 'ms'];
|
|
|
|
/// Clear saved language preference
|
|
Future<void> clearSavedLanguage() async {
|
|
await _prefs.remove(_languageKey);
|
|
_locale = const Locale(_defaultLanguage);
|
|
notifyListeners();
|
|
}
|
|
|
|
/// Reset to default language
|
|
Future<void> resetToDefault() async {
|
|
await setLocale(const Locale(_defaultLanguage));
|
|
}
|
|
} |