Merge branch 'dev' into Issues-on-payments-timecard-availability-screens-01-02-03-04

This commit is contained in:
Achintha Isuru
2026-01-30 11:19:07 -05:00
committed by GitHub
188 changed files with 25143 additions and 22236 deletions

View File

@@ -1,6 +1,8 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../domain/usecases/get_default_locale_use_case.dart';
import '../domain/usecases/get_locale_use_case.dart';
import '../domain/usecases/get_supported_locales_use_case.dart';
import '../domain/usecases/set_locale_use_case.dart';
import '../l10n/strings.g.dart';
import 'locale_event.dart';
@@ -11,23 +13,39 @@ import 'locale_state.dart';
/// It coordinates the flow between user language requests and persistent storage
/// using [SetLocaleUseCase] and [GetLocaleUseCase].
class LocaleBloc extends Bloc<LocaleEvent, LocaleState> {
final GetLocaleUseCase getLocaleUseCase;
final SetLocaleUseCase setLocaleUseCase;
/// Creates a [LocaleBloc] with the required use cases.
LocaleBloc({required this.getLocaleUseCase, required this.setLocaleUseCase})
: super(LocaleState.initial()) {
LocaleBloc({
required this.getLocaleUseCase,
required this.setLocaleUseCase,
required this.getSupportedLocalesUseCase,
required this.getDefaultLocaleUseCase,
}) : super(LocaleState.initial()) {
on<ChangeLocale>(_onChangeLocale);
on<LoadLocale>(_onLoadLocale);
/// Initial event
add(const LoadLocale());
}
/// Use case for retrieving the saved locale.
final GetLocaleUseCase getLocaleUseCase;
/// Use case for saving the selected locale.
final SetLocaleUseCase setLocaleUseCase;
/// Use case for retrieving supported locales.
final GetSupportedLocalesUseCase getSupportedLocalesUseCase;
/// Use case for retrieving the default locale.
final GetDefaultLocaleUseCase getDefaultLocaleUseCase;
/// Handles the [ChangeLocale] event by saving it via the use case and emitting new state.
Future<void> _onChangeLocale(
ChangeLocale event,
Emitter<LocaleState> emit,
) async {
// 1. Update slang settings
LocaleSettings.setLocaleRaw(event.locale.languageCode);
await LocaleSettings.setLocaleRaw(event.locale.languageCode);
// 2. Persist using Use Case
await setLocaleUseCase(event.locale);
@@ -46,11 +64,14 @@ class LocaleBloc extends Bloc<LocaleEvent, LocaleState> {
LoadLocale event,
Emitter<LocaleState> emit,
) async {
final Locale? savedLocale = await getLocaleUseCase();
final Locale locale = savedLocale ?? const Locale('en');
final Locale savedLocale = await getLocaleUseCase();
final List<Locale> supportedLocales = getSupportedLocalesUseCase();
LocaleSettings.setLocaleRaw(locale.languageCode);
await LocaleSettings.setLocaleRaw(savedLocale.languageCode);
emit(LocaleState(locale: locale, supportedLocales: state.supportedLocales));
emit(LocaleState(
locale: savedLocale,
supportedLocales: supportedLocales,
));
}
}

View File

@@ -1,20 +1,21 @@
import 'package:flutter/material.dart';
import '../l10n/strings.g.dart';
/// Represents the current state of the application's localization.
class LocaleState {
/// Creates a [LocaleState] with the specified [locale].
const LocaleState({required this.locale, required this.supportedLocales});
/// The initial state of the application, defaulting to English.
factory LocaleState.initial() => LocaleState(
locale: AppLocaleUtils.findDeviceLocale().flutterLocale,
supportedLocales: AppLocaleUtils.supportedLocales,
);
/// The current active locale.
final Locale locale;
/// The list of supported locales for the application.
final List<Locale> supportedLocales;
/// Creates a [LocaleState] with the specified [locale].
const LocaleState({required this.locale, required this.supportedLocales});
/// The initial state of the application, defaulting to English.
factory LocaleState.initial() => LocaleState(
locale: const Locale('es'),
supportedLocales: AppLocaleUtils.supportedLocales,
);
}

View File

@@ -1,4 +1,6 @@
import 'dart:ui';
import 'package:core_localization/src/l10n/strings.g.dart';
import '../../domain/repositories/locale_repository_interface.dart';
import '../datasources/locale_local_data_source.dart';
@@ -7,22 +9,36 @@ import '../datasources/locale_local_data_source.dart';
/// This class handles the mapping between domain [Locale] objects and the raw
/// strings handled by the [LocaleLocalDataSource].
class LocaleRepositoryImpl implements LocaleRepositoryInterface {
final LocaleLocalDataSource _localDataSource;
/// Creates a [LocaleRepositoryImpl] with the provided [localDataSource].
LocaleRepositoryImpl({required this.localDataSource});
/// Creates a [LocaleRepositoryImpl] with the provided [_localDataSource].
LocaleRepositoryImpl(this._localDataSource);
final LocaleLocalDataSource localDataSource;
@override
Future<void> saveLocale(Locale locale) {
return _localDataSource.saveLanguageCode(locale.languageCode);
return localDataSource.saveLanguageCode(locale.languageCode);
}
@override
Future<Locale?> getSavedLocale() async {
final String? languageCode = await _localDataSource.getLanguageCode();
Future<Locale> getSavedLocale() async {
return getDefaultLocale();
/// TODO: FEATURE_NOT_IMPLEMENTED: Implement saved locale retrieval later
final String? languageCode = await localDataSource.getLanguageCode();
if (languageCode != null) {
return Locale(languageCode);
}
return null;
}
@override
Locale getDefaultLocale() {
final Locale deviceLocale = AppLocaleUtils.findDeviceLocale().flutterLocale;
if (getSupportedLocales().contains(deviceLocale)) {
return deviceLocale;
}
return const Locale('en');
}
@override
List<Locale> getSupportedLocales() => AppLocaleUtils.supportedLocales;
}

View File

@@ -13,5 +13,11 @@ abstract interface class LocaleRepositoryInterface {
/// Retrieves the saved [locale] from persistent storage.
///
/// Returns `null` if no locale has been previously saved.
Future<Locale?> getSavedLocale();
Future<Locale> getSavedLocale();
/// Retrieves the default [Locale] for the application.
Locale getDefaultLocale();
/// Retrieves the list of supported [Locale]s.
List<Locale> getSupportedLocales();
}

View File

@@ -0,0 +1,15 @@
import 'dart:ui';
import '../repositories/locale_repository_interface.dart';
/// Use case to retrieve the default locale.
class GetDefaultLocaleUseCase {
final LocaleRepositoryInterface _repository;
/// Creates a [GetDefaultLocaleUseCase] with the required [LocaleRepositoryInterface].
GetDefaultLocaleUseCase(this._repository);
/// Retrieves the default locale.
Locale call() {
return _repository.getDefaultLocale();
}
}

View File

@@ -13,7 +13,7 @@ class GetLocaleUseCase extends NoInputUseCase<Locale?> {
GetLocaleUseCase(this._repository);
@override
Future<Locale?> call() {
Future<Locale> call() {
return _repository.getSavedLocale();
}
}

View File

@@ -0,0 +1,15 @@
import 'dart:ui';
import '../repositories/locale_repository_interface.dart';
/// Use case to retrieve the list of supported locales.
class GetSupportedLocalesUseCase {
final LocaleRepositoryInterface _repository;
/// Creates a [GetSupportedLocalesUseCase] with the required [LocaleRepositoryInterface].
GetSupportedLocalesUseCase(this._repository);
/// Retrieves the supported locales.
List<Locale> call() {
return _repository.getSupportedLocales();
}
}

View File

@@ -6,7 +6,7 @@
/// Locales: 2
/// Strings: 1038 (519 per locale)
///
/// Built on 2026-01-28 at 09:41 UTC
/// Built on 2026-01-29 at 15:50 UTC
// coverage:ignore-file
// ignore_for_file: type=lint, unused_import

View File

@@ -3,7 +3,9 @@ import 'package:shared_preferences/shared_preferences.dart';
import 'data/datasources/locale_local_data_source.dart';
import 'data/repositories_impl/locale_repository_impl.dart';
import 'domain/repositories/locale_repository_interface.dart';
import 'domain/usecases/get_default_locale_use_case.dart';
import 'domain/usecases/get_locale_use_case.dart';
import 'domain/usecases/get_supported_locales_use_case.dart';
import 'domain/usecases/set_locale_use_case.dart';
import 'bloc/locale_bloc.dart';
@@ -18,28 +20,36 @@ class LocalizationModule extends Module {
i.addInstance<SharedPreferencesAsync>(SharedPreferencesAsync());
// Data Sources
i.addSingleton<LocaleLocalDataSource>(
i.addLazySingleton<LocaleLocalDataSource>(
() => LocaleLocalDataSourceImpl(i.get<SharedPreferencesAsync>()),
);
// Repositories
i.addSingleton<LocaleRepositoryInterface>(
() => LocaleRepositoryImpl(i.get<LocaleLocalDataSource>()),
i.addLazySingleton<LocaleRepositoryInterface>(
() => LocaleRepositoryImpl(localDataSource: i.get<LocaleLocalDataSource>()),
);
// Use Cases
i.addSingleton<GetLocaleUseCase>(
i.addLazySingleton<GetLocaleUseCase>(
() => GetLocaleUseCase(i.get<LocaleRepositoryInterface>()),
);
i.addSingleton<SetLocaleUseCase>(
i.addLazySingleton<SetLocaleUseCase>(
() => SetLocaleUseCase(i.get<LocaleRepositoryInterface>()),
);
i.addLazySingleton<GetSupportedLocalesUseCase>(
() => GetSupportedLocalesUseCase(i.get<LocaleRepositoryInterface>()),
);
i.addLazySingleton<GetDefaultLocaleUseCase>(
() => GetDefaultLocaleUseCase(i.get<LocaleRepositoryInterface>()),
);
// BLoCs
i.addSingleton<LocaleBloc>(
i.add<LocaleBloc>(
() => LocaleBloc(
getLocaleUseCase: i.get<GetLocaleUseCase>(),
setLocaleUseCase: i.get<SetLocaleUseCase>(),
getSupportedLocalesUseCase: i.get<GetSupportedLocalesUseCase>(),
getDefaultLocaleUseCase: i.get<GetDefaultLocaleUseCase>(),
),
);
}