diff --git a/lib/main.dart b/lib/main.dart index f9503ce..b76f300 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -5,21 +5,26 @@ import 'package:gui/src/core/constants/configurations.dart'; import 'package:gui/src/core/router/app_router.dart'; import 'package:gui/src/core/utils/gen/localization/codegen_loader.g.dart'; import 'package:gui/src/features/main/theme/bloc/theme_bloc.dart'; +import 'src/core/services/shared_preferences_service.dart'; import 'src/features/main/language/presentation/bloc/language_bloc.dart'; void main() async { + WidgetsFlutterBinding.ensureInitialized(); await EasyLocalization.ensureInitialized(); + + final sharedPreferencesService = await SharedPreferencesService.initialize(); + runApp( MultiBlocProvider( providers: [ BlocProvider( - create: (_) => LanguageBloc(), + create: (_) => LanguageBloc(sharedPreferencesService), ), BlocProvider( create: (_) => ThemeBloc(), ), ], - child: MyApp(), + child: const MyApp(), ), ); } @@ -38,6 +43,11 @@ class MyApp extends StatelessWidget { assetLoader: const CodegenLoader(), child: BlocBuilder( builder: (context, languageState) { + if (context.locale != languageState.selectedLanguage.value) { + WidgetsBinding.instance.addPostFrameCallback((_) { + context.setLocale(languageState.selectedLanguage.value); + }); + } return BlocBuilder( builder: (context, themeState) { return MaterialApp.router( diff --git a/lib/presentation/bloc/language_bloc/language_bloc.dart b/lib/presentation/bloc/language_bloc/language_bloc.dart deleted file mode 100644 index ae23aee..0000000 --- a/lib/presentation/bloc/language_bloc/language_bloc.dart +++ /dev/null @@ -1,16 +0,0 @@ -import 'package:bloc/bloc.dart'; -import '../../../src/features/main/language/presentation/bloc/language_bloc.dart'; - -const languagePrefsKey = 'languagePrefs'; - -class LanguageBloc extends Bloc { - LanguageBloc() : super(const LanguageState()) { - on(onChangeLanguage); - } - Future onChangeLanguage( - ChangeLanguage event, - Emitter emit, - ) async { - emit(state.copyWith(selectedLanguage: event.selectedLanguage)); - } -} diff --git a/lib/src/core/constants/app_constants.dart b/lib/src/core/constants/app_constants.dart new file mode 100644 index 0000000..1442fa6 --- /dev/null +++ b/lib/src/core/constants/app_constants.dart @@ -0,0 +1,4 @@ +class AppConstants { + static const String languagePrefsKey = 'languagePrefs'; + static const String themePrefsKey = 'themePrefs'; +} diff --git a/lib/src/core/services/shared_preferences_service.dart b/lib/src/core/services/shared_preferences_service.dart new file mode 100644 index 0000000..dac155e --- /dev/null +++ b/lib/src/core/services/shared_preferences_service.dart @@ -0,0 +1,26 @@ +import 'package:gui/src/core/constants/app_constants.dart'; +import 'package:gui/src/features/main/language/data/language_model.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +class SharedPreferencesService { + SharedPreferencesService(this._preferences); + final SharedPreferences _preferences; + + static Future initialize() async { + final preferences = await SharedPreferences.getInstance(); + return SharedPreferencesService(preferences); + } + + String getSelectedLanguage() { + return _preferences.getString(AppConstants.languagePrefsKey) ?? + Language.english.code; + } + + Future setSelectedLanguage(String languageCode) { + return _preferences.setString(AppConstants.languagePrefsKey, languageCode); + } + + Future saveSelectedLanguage(String languageCode) { + return setSelectedLanguage(languageCode); + } +} diff --git a/lib/src/features/main/language/data/language_model.dart b/lib/src/features/main/language/data/language_model.dart index ab33387..a8c5498 100644 --- a/lib/src/features/main/language/data/language_model.dart +++ b/lib/src/features/main/language/data/language_model.dart @@ -4,21 +4,26 @@ enum Language { english( Locale('en', 'US'), 'English', + 'en', ), spanish( Locale('es', 'ES'), 'Español', + 'es', ), french( Locale('fr', 'FR'), 'Français', + 'fr', ); const Language( this.value, this.text, + this.code, ); final Locale value; final String text; + final String code; } diff --git a/lib/src/features/main/language/presentation/bloc/language_bloc.dart b/lib/src/features/main/language/presentation/bloc/language_bloc.dart index 3829c57..0f92234 100644 --- a/lib/src/features/main/language/presentation/bloc/language_bloc.dart +++ b/lib/src/features/main/language/presentation/bloc/language_bloc.dart @@ -1,17 +1,46 @@ import 'package:bloc/bloc.dart'; import 'package:equatable/equatable.dart'; import 'package:gui/src/features/main/language/data/language_model.dart'; +import '../../../../../core/services/shared_preferences_service.dart'; + part 'language_event.dart'; part 'language_state.dart'; class LanguageBloc extends Bloc { - LanguageBloc() : super(const LanguageState()) { - on(onChangeLanguage); + LanguageBloc(this._sharedPreferencesService) : super(const LanguageState()) { + on(_onInitializeLanguage); + on(_onChangeLanguage); + add(InitializeLanguageEvent()); // Trigger initialization on creation } - Future onChangeLanguage( + + final SharedPreferencesService _sharedPreferencesService; + + Future _onInitializeLanguage( + InitializeLanguageEvent event, + Emitter emit, + ) async { + final languageCode = _sharedPreferencesService.getSelectedLanguage(); + + final language = languageCode.isNotEmpty + ? Language.values.firstWhere( + (lang) => lang.code == languageCode, + orElse: () => Language.english, + ) + : Language.english; + + await _sharedPreferencesService.saveSelectedLanguage( + language.code, + ); + emit(state.copyWith(selectedLanguage: language)); + } + + Future _onChangeLanguage( ChangeLanguage event, Emitter emit, ) async { + await _sharedPreferencesService.saveSelectedLanguage( + event.selectedLanguage.code, + ); emit(state.copyWith(selectedLanguage: event.selectedLanguage)); } } diff --git a/lib/src/features/main/language/presentation/bloc/language_state.dart b/lib/src/features/main/language/presentation/bloc/language_state.dart index 3b646f8..8167884 100644 --- a/lib/src/features/main/language/presentation/bloc/language_state.dart +++ b/lib/src/features/main/language/presentation/bloc/language_state.dart @@ -2,19 +2,22 @@ part of 'language_bloc.dart'; class LanguageState extends Equatable { const LanguageState({ - this.selectedLanguage = Language.english, // Default to English + this.selectedLanguage = Language.english, }); final Language selectedLanguage; - @override - List get props => [selectedLanguage]; - - LanguageState copyWith({Language? selectedLanguage}) { + LanguageState copyWith({ + Language? selectedLanguage, + bool? isInitialized, + }) { return LanguageState( selectedLanguage: selectedLanguage ?? this.selectedLanguage, ); } + + @override + List get props => [selectedLanguage]; } class LanguageInitial extends LanguageState { diff --git a/pubspec.yaml b/pubspec.yaml index d4af836..6aa0cf5 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -26,6 +26,7 @@ dependencies: go_router: ^14.6.1 intl: ^0.19.0 json_annotation: ^4.9.0 + shared_preferences: ^2.3.4 dev_dependencies: build_runner: