diff --git a/app/lib/app/data/data.dart b/app/lib/app/data/data.dart index 1619b9d1..81307378 100644 --- a/app/lib/app/data/data.dart +++ b/app/lib/app/data/data.dart @@ -1,10 +1,18 @@ export 'repository/app_repositoty_impl.dart'; export 'repository/theme_repository_impl.dart'; export 'repository/auth_repositoty_impl.dart'; -export 'source/app_local_data_source.dart'; -export 'source/theme_local_data_source.dart'; export 'source/auth_local_data_source.dart'; export 'source/auth_remote_data_source.dart'; +export 'source/theme_local_data_source.dart'; +export 'source/app_local_data_source.dart'; +export 'source/local/app_local_data_source_impl.dart'; +export 'source/local/theme_local_data_source_impl.dart'; +export 'source/local/auth_local_data_source_impl.dart'; +export 'source/remote/auth_remote_data_source_impl.dart'; +export 'source/mock/auth_local_data_source_mock.dart'; +export 'source/mock/auth_remote_data_source_mock.dart'; +export 'source/mock/theme_local_data_source_mock.dart'; +export 'source/mock/app_local_data_source_mock.dart'; export 'models/user_model.dart'; export 'models/token_response.dart'; export 'models/user_data_response.dart'; diff --git a/app/lib/app/data/repository/auth_repositoty_impl.dart b/app/lib/app/data/repository/auth_repositoty_impl.dart index fab4875c..7b4ac921 100644 --- a/app/lib/app/data/repository/auth_repositoty_impl.dart +++ b/app/lib/app/data/repository/auth_repositoty_impl.dart @@ -15,9 +15,7 @@ final class AuthRepositoryImpl implements AuthRepository { final AuthRemoteDataSource remoteDataSource; @override - UserEntity? get init { - return localDataSource.init; - } + UserEntity? get init => localDataSource.init; @override Future setUserData(UserEntity userEntity) async { @@ -35,24 +33,18 @@ final class AuthRepositoryImpl implements AuthRepository { String languageCode, Gender gender, ) async { - try { - final res = await remoteDataSource.signInWithGoogle(languageCode, gender); - return res.fold( - Left.new, - (r) => Right( - UserEntity( - accessToken: r.accessToken, - username: r.username, - gender: r.gender, - localeCode: r.localeCode, - ), + final res = await remoteDataSource.signInWithGoogle(languageCode, gender); + return res.fold( + Left.new, + (r) => Right( + UserEntity( + accessToken: r.accessToken, + username: r.username, + gender: r.gender, + localeCode: r.localeCode, ), - ); - } catch (e, s) { - log('signWithGoogle: error: $e\n$s'); - MqCrashlytics.report(e, s); - return Left(AuthenticationExc(message: e.toString())); - } + ), + ); } @override @@ -60,24 +52,18 @@ final class AuthRepositoryImpl implements AuthRepository { String languageCode, Gender gender, ) async { - try { - final res = await remoteDataSource.signInWithApple(languageCode, gender); - return res.fold( - Left.new, - (r) => Right( - UserEntity( - accessToken: r.accessToken, - username: r.username, - gender: r.gender, - localeCode: r.localeCode, - ), + final res = await remoteDataSource.signInWithApple(languageCode, gender); + return res.fold( + Left.new, + (r) => Right( + UserEntity( + accessToken: r.accessToken, + username: r.username, + gender: r.gender, + localeCode: r.localeCode, ), - ); - } catch (e, s) { - MqCrashlytics.report(e, s); - log('signWithGoogle: error: $e\n$s'); - return Left(AuthenticationExc(message: e.toString())); - } + ), + ); } @override diff --git a/app/lib/app/data/repository/theme_repository_impl.dart b/app/lib/app/data/repository/theme_repository_impl.dart index a24e259b..59cd2633 100644 --- a/app/lib/app/data/repository/theme_repository_impl.dart +++ b/app/lib/app/data/repository/theme_repository_impl.dart @@ -9,9 +9,7 @@ final class ThemeRepositoryImpl implements ThemeRepository { final ThemeLocalDataSource themeLocalDataSource; @override - CustomTheme get getInitialThemeState { - return themeLocalDataSource.initialTheme; - } + CustomTheme get getInitialThemeState => themeLocalDataSource.initialTheme; @override Future saveThemePrimaryColor(int index) async { diff --git a/app/lib/app/data/source/app_local_data_source.dart b/app/lib/app/data/source/app_local_data_source.dart index ab7d599b..5ea06698 100644 --- a/app/lib/app/data/source/app_local_data_source.dart +++ b/app/lib/app/data/source/app_local_data_source.dart @@ -1,13 +1,3 @@ -import 'package:flutter/material.dart'; -import 'package:package_info_plus/package_info_plus.dart'; - -@immutable -final class AppLocalDataSource { - const AppLocalDataSource({ - required this.packageInfo, - }); - - final PackageInfo packageInfo; - - String get appVersion => packageInfo.version; +abstract class AppLocalDataSource { + String get appVersion; } diff --git a/app/lib/app/data/source/auth_local_data_source.dart b/app/lib/app/data/source/auth_local_data_source.dart index faf8dccc..b3a4986a 100644 --- a/app/lib/app/data/source/auth_local_data_source.dart +++ b/app/lib/app/data/source/auth_local_data_source.dart @@ -1,53 +1,10 @@ -import 'package:meta/meta.dart'; -import 'package:mq_storage/mq_storage.dart'; import 'package:my_quran/app/app.dart'; -import 'package:my_quran/constants/contants.dart'; -@immutable -final class AuthLocalDataSource { - const AuthLocalDataSource(this.storage); - - final PreferencesStorage storage; - - UserEntity? get init { - final userToken = storage.readString(key: StorageKeys.tokenKey); - final userGender = storage.readString(key: StorageKeys.genderKey); - final username = storage.readString(key: StorageKeys.usernameKey); - final localeCode = storage.readString(key: StorageKeys.localeKey); - if (userToken == null && userGender == null && username == null) return null; - return UserEntity( - accessToken: userToken!, - username: username!, - gender: userGender == Gender.male.name ? Gender.male : Gender.female, - localeCode: localeCode ?? 'en', - ); - } - - String? getToken() => storage.readString(key: StorageKeys.tokenKey); - - Future saveUserData(UserEntity userEntity) async { - await Future.wait([ - storage.writeString(key: StorageKeys.localeKey, value: userEntity.localeCode), - storage.writeString(key: StorageKeys.genderKey, value: userEntity.gender.name), - storage.writeString(key: StorageKeys.usernameKey, value: userEntity.username), - ]); - } - - Future saveGender(Gender gender) { - return storage.writeString( - key: StorageKeys.genderKey, - value: gender.name, - ); - } - - Future saveLocaleCode(String localeCode) { - return storage.writeString( - key: StorageKeys.localeKey, - value: localeCode, - ); - } - - Future logoutLocal() async { - await storage.clear(); - } +abstract class AuthLocalDataSource { + UserEntity? get init; + String? getToken(); + Future saveUserData(UserEntity userEntity); + Future saveGender(Gender gender); + Future saveLocaleCode(String localeCode); + Future logoutLocal(); } diff --git a/app/lib/app/data/source/auth_remote_data_source.dart b/app/lib/app/data/source/auth_remote_data_source.dart index 9ea94695..e5a57563 100644 --- a/app/lib/app/data/source/auth_remote_data_source.dart +++ b/app/lib/app/data/source/auth_remote_data_source.dart @@ -1,155 +1,36 @@ -import 'package:meta/meta.dart'; -import 'package:mq_storage/mq_storage.dart'; import 'package:my_quran/app/app.dart'; -import 'package:my_quran/config/config.dart'; -import 'package:my_quran/constants/contants.dart'; import 'package:my_quran/core/core.dart'; -@immutable -final class AuthRemoteDataSource { - const AuthRemoteDataSource({ - required this.client, - required this.storage, - required this.soccialAuth, - required this.isIntegrationTest, - }); +abstract class AuthRemoteDataSource { + Future loginWithEmail(String email); - final MqDio client; - final PreferencesStorage storage; - final SoccialAuth soccialAuth; - final bool isIntegrationTest; + Future> fetchSmsCode({ + required String code, + required String languageCode, + required Gender gender, + }); Future> signInWithGoogle( String languageCode, Gender gender, - ) async { - final googleAuth = await _getGoogleAuth(); - - final token = await client.postType( - apiConst.loginWithGoogle, - fromJson: TokenResponse.fromJson, - body: {'access_token': googleAuth.accessToken}, - ); - - return token.fold(Left.new, (r) async { - final user = UserModelResponse( - accessToken: r.key, - username: googleAuth.name, - gender: gender, - localeCode: languageCode, - ); - - await storage.writeString(key: StorageKeys.tokenKey, value: user.accessToken); - - return Right(user); - }); - } - - Future<_UserReqParam> _getGoogleAuth() async { - if (isIntegrationTest) { - return const _UserReqParam( - name: 'Test User', - accessToken: r'myquran_te$t_t0ken', - ); - } else { - final googleAuth = await soccialAuth.signInWithGoogle(); - final accessToken = googleAuth.credential?.accessToken ?? ''; - final username = googleAuth.user?.displayName ?? ''; - return _UserReqParam( - name: username, - accessToken: accessToken, - ); - } - } + ); Future> signInWithApple( String languageCode, Gender gender, - ) async { - final appleAuth = await _getAppleAuth(); - - final token = await client.postType( - apiConst.loginWithApple, - fromJson: TokenResponse.fromJson, - body: {'access_token': appleAuth.accessToken}, - ); + ); - return token.fold(Left.new, (r) async { - final user = UserModelResponse( - accessToken: r.key, - username: appleAuth.name, - gender: gender, - localeCode: languageCode, - ); - - await storage.writeString(key: StorageKeys.tokenKey, value: user.accessToken); - - return Right(user); - }); - } - - Future<_UserReqParam> _getAppleAuth() async { - if (isIntegrationTest) { - return const _UserReqParam( - name: 'Test User', - accessToken: r'myquran_te$t_t0ken', - ); - } else { - final appleAuth = await soccialAuth.signInWithApple(); - final accessToken = appleAuth.credential?.accessToken ?? ''; - final username = appleAuth.user?.displayName ?? ''; - return _UserReqParam( - name: username, - accessToken: accessToken, - ); - } - } - - Future> saveUserData(UserEntity userEntity) { - return client.putType( - apiConst.putProfile(userEntity.accessToken), - fromJson: UserDataResponse.fromJson, - body: { - 'gender': userEntity.gender.name.toUpperCase(), - 'language': userEntity.localeCode.toUpperCase(), - }, - ); - } + Future> saveUserData(UserEntity userEntity); Future> pathGender({ required String userId, required Gender gender, - }) { - return client.patchType( - apiConst.putProfile(userId), - fromJson: UserDataResponse.fromJson, - body: {'gender': gender.name.toUpperCase()}, - ); - } + }); Future> pathLocaleCode({ required String userId, required String localeCode, - }) { - return client.patchType( - apiConst.putProfile(userId), - fromJson: UserDataResponse.fromJson, - body: {'language': localeCode.toUpperCase()}, - ); - } - - Future logoutRemote() async { - await soccialAuth.logOut(); - } -} - -@immutable -final class _UserReqParam { - const _UserReqParam({ - required this.name, - required this.accessToken, }); - final String name; - final String accessToken; + Future logoutRemote(); } diff --git a/app/lib/app/data/source/local/app_local_data_source_impl.dart b/app/lib/app/data/source/local/app_local_data_source_impl.dart new file mode 100644 index 00000000..8f8ad093 --- /dev/null +++ b/app/lib/app/data/source/local/app_local_data_source_impl.dart @@ -0,0 +1,15 @@ +import 'package:flutter/material.dart'; +import 'package:my_quran/app/app.dart'; +import 'package:package_info_plus/package_info_plus.dart'; + +@immutable +final class AppLocalDataSourceImpl implements AppLocalDataSource { + const AppLocalDataSourceImpl({ + required this.packageInfo, + }); + + final PackageInfo packageInfo; + + @override + String get appVersion => packageInfo.version; +} diff --git a/app/lib/app/data/source/local/auth_local_data_source_impl.dart b/app/lib/app/data/source/local/auth_local_data_source_impl.dart new file mode 100644 index 00000000..8728965a --- /dev/null +++ b/app/lib/app/data/source/local/auth_local_data_source_impl.dart @@ -0,0 +1,59 @@ +import 'package:meta/meta.dart'; +import 'package:mq_storage/mq_storage.dart'; +import 'package:my_quran/app/app.dart'; +import 'package:my_quran/constants/contants.dart'; + +@immutable +final class AuthLocalDataSourceImpl implements AuthLocalDataSource { + const AuthLocalDataSourceImpl(this.storage); + + final PreferencesStorage storage; + + @override + UserEntity? get init { + final userToken = storage.readString(key: StorageKeys.tokenKey); + final userGender = storage.readString(key: StorageKeys.genderKey); + final username = storage.readString(key: StorageKeys.usernameKey); + final localeCode = storage.readString(key: StorageKeys.localeKey); + if (userToken == null && userGender == null && username == null) return null; + return UserEntity( + accessToken: userToken!, + username: username!, + gender: userGender == Gender.male.name ? Gender.male : Gender.female, + localeCode: localeCode ?? 'en', + ); + } + + @override + String? getToken() => storage.readString(key: StorageKeys.tokenKey); + + @override + Future saveUserData(UserEntity userEntity) async { + await Future.wait([ + storage.writeString(key: StorageKeys.localeKey, value: userEntity.localeCode), + storage.writeString(key: StorageKeys.genderKey, value: userEntity.gender.name), + storage.writeString(key: StorageKeys.usernameKey, value: userEntity.username), + ]); + } + + @override + Future saveGender(Gender gender) { + return storage.writeString( + key: StorageKeys.genderKey, + value: gender.name, + ); + } + + @override + Future saveLocaleCode(String localeCode) { + return storage.writeString( + key: StorageKeys.localeKey, + value: localeCode, + ); + } + + @override + Future logoutLocal() async { + await storage.clear(); + } +} diff --git a/app/lib/app/data/source/local/theme_local_data_source_impl.dart b/app/lib/app/data/source/local/theme_local_data_source_impl.dart new file mode 100644 index 00000000..c6394e97 --- /dev/null +++ b/app/lib/app/data/source/local/theme_local_data_source_impl.dart @@ -0,0 +1,34 @@ +import 'package:flutter/material.dart'; +import 'package:my_quran/app/app.dart'; +import 'package:my_quran/constants/contants.dart'; +import 'package:mq_storage/mq_storage.dart'; +import 'package:my_quran/theme/theme.dart'; + +@immutable +final class ThemeLocalDataSourceImpl implements ThemeLocalDataSource { + const ThemeLocalDataSourceImpl(this.storage); + final PreferencesStorage storage; + + @override + CustomTheme get initialTheme { + final isDark = storage.readBool(key: StorageKeys.modeKey); + final cachedColorIndex = storage.readInt(key: StorageKeys.colorKey); + final brightness = (isDark ?? false) ? Brightness.dark : Brightness.light; + final targetColor = _getColor(cachedColorIndex); + return CustomTheme(brightness, targetColor); + } + + @override + Future saveThemePrimaryColor(int index) async { + await storage.writeInt(key: StorageKeys.colorKey, value: index); + } + + @override + Future saveThemeMode({required bool isDark}) async { + await storage.writeBool(key: StorageKeys.modeKey, value: isDark); + } + + Color _getColor(int? cacheColor) { + return TargetColor.fromIndex(cacheColor ?? 0).color; + } +} diff --git a/app/lib/app/data/source/mock/app_local_data_source_mock.dart b/app/lib/app/data/source/mock/app_local_data_source_mock.dart new file mode 100644 index 00000000..203b9cbc --- /dev/null +++ b/app/lib/app/data/source/mock/app_local_data_source_mock.dart @@ -0,0 +1,10 @@ +import 'package:flutter/material.dart'; +import 'package:my_quran/app/app.dart'; + +@immutable +final class AppLocalDataSourceMock implements AppLocalDataSource { + const AppLocalDataSourceMock(); + + @override + String get appVersion => '1.3.1'; +} diff --git a/app/lib/app/data/source/mock/auth_local_data_source_mock.dart b/app/lib/app/data/source/mock/auth_local_data_source_mock.dart new file mode 100644 index 00000000..caa6d55b --- /dev/null +++ b/app/lib/app/data/source/mock/auth_local_data_source_mock.dart @@ -0,0 +1,25 @@ +import 'package:meta/meta.dart'; +import 'package:my_quran/app/app.dart'; + +@immutable +final class AuthLocalDataSourceMock implements AuthLocalDataSource { + const AuthLocalDataSourceMock(); + + @override + UserEntity? get init => null; + + @override + String? getToken() => ''; + + @override + Future saveUserData(UserEntity userEntity) async {} + + @override + Future saveGender(Gender gender) => Future.value(); + + @override + Future saveLocaleCode(String localeCode) => Future.value(); + + @override + Future logoutLocal() async => Future.value(); +} diff --git a/app/lib/app/data/source/mock/auth_remote_data_source_mock.dart b/app/lib/app/data/source/mock/auth_remote_data_source_mock.dart new file mode 100644 index 00000000..7848cbe8 --- /dev/null +++ b/app/lib/app/data/source/mock/auth_remote_data_source_mock.dart @@ -0,0 +1,92 @@ +import 'package:meta/meta.dart'; +import 'package:my_quran/app/app.dart'; + +import 'package:my_quran/core/core.dart'; + +@immutable +final class AuthRemoteDataSourceMock implements AuthRemoteDataSource { + const AuthRemoteDataSourceMock(); + + @override + Future loginWithEmail(String email) async {} + + @override + Future> fetchSmsCode({ + required String code, + required String languageCode, + required Gender gender, + }) async { + final user = UserModelResponse( + accessToken: r'myquran_te$t_t0ken', + username: 'Test User', + gender: gender, + localeCode: languageCode, + ); + + return Right(user); + } + + @override + Future> signInWithGoogle( + String languageCode, + Gender gender, + ) async { + final user = UserModelResponse( + accessToken: 'mock_token_google', + username: 'Mock Google User', + gender: gender, + localeCode: languageCode, + ); + return Right(user); + } + + @override + Future> signInWithApple( + String languageCode, + Gender gender, + ) async { + final user = UserModelResponse( + accessToken: 'mock_token_apple', + username: 'Mock Apple User', + gender: gender, + localeCode: languageCode, + ); + return Right(user); + } + + @override + Future> saveUserData(UserEntity userEntity) async { + final response = UserDataResponse( + gender: userEntity.gender.toString(), + language: userEntity.localeCode, + ); + return Right(response); + } + + @override + Future> pathGender({ + required String userId, + required Gender gender, + }) async { + final response = UserDataResponse( + gender: Gender.male.toString(), + language: 'en', + ); + return Right(response); + } + + @override + Future> pathLocaleCode({ + required String userId, + required String localeCode, + }) async { + final response = UserDataResponse( + gender: Gender.male.toString(), + language: 'en', + ); + return Right(response); + } + + @override + Future logoutRemote() async {} +} diff --git a/app/lib/app/data/source/mock/theme_local_data_source_mock.dart b/app/lib/app/data/source/mock/theme_local_data_source_mock.dart new file mode 100644 index 00000000..c21948cc --- /dev/null +++ b/app/lib/app/data/source/mock/theme_local_data_source_mock.dart @@ -0,0 +1,17 @@ +import 'package:flutter/material.dart'; +import 'package:my_quran/app/app.dart'; +import 'package:my_quran/theme/theme.dart'; + +@immutable +final class ThemeLocalDataSourceMock implements ThemeLocalDataSource { + const ThemeLocalDataSourceMock(); + + @override + CustomTheme get initialTheme => const CustomTheme(Brightness.light, AppColors.red); + + @override + Future saveThemePrimaryColor(int index) async {} + + @override + Future saveThemeMode({required bool isDark}) async {} +} diff --git a/app/lib/app/data/source/remote/auth_remote_data_source_impl.dart b/app/lib/app/data/source/remote/auth_remote_data_source_impl.dart new file mode 100644 index 00000000..3d4615b7 --- /dev/null +++ b/app/lib/app/data/source/remote/auth_remote_data_source_impl.dart @@ -0,0 +1,208 @@ +import 'package:meta/meta.dart'; +import 'package:mq_storage/mq_storage.dart'; +import 'package:my_quran/app/app.dart'; +import 'package:my_quran/config/config.dart'; +import 'package:my_quran/constants/contants.dart'; +import 'package:my_quran/core/core.dart'; + +@immutable +final class AuthRemoteDataSourceImpl implements AuthRemoteDataSource { + const AuthRemoteDataSourceImpl({ + required this.client, + required this.storage, + required this.soccialAuth, + required this.isIntegrationTest, + }); + + final MqDio client; + final PreferencesStorage storage; + final SoccialAuth soccialAuth; + final bool isIntegrationTest; + + @override + Future> signInWithGoogle( + String languageCode, + Gender gender, + ) async { + final googleAuth = await _getGoogleAuth(); + + final token = await client.postType( + apiConst.loginWithGoogle, + fromJson: TokenResponse.fromJson, + body: {'access_token': googleAuth.accessToken}, + ); + + return token.fold(Left.new, (r) async { + final user = UserModelResponse( + accessToken: r.key, + username: googleAuth.name, + gender: gender, + localeCode: languageCode, + ); + + await storage.writeString(key: StorageKeys.tokenKey, value: user.accessToken); + + return Right(user); + }); + } + + Future<_UserReqParam> _getGoogleAuth() async { + if (isIntegrationTest) { + return const _UserReqParam( + name: 'Test User', + accessToken: r'myquran_te$t_t0ken', + ); + } else { + final googleAuth = await soccialAuth.signInWithGoogle(); + final accessToken = googleAuth.credential?.accessToken ?? ''; + final username = googleAuth.user?.displayName ?? ''; + return _UserReqParam( + name: username, + accessToken: accessToken, + ); + } + } + + @override + Future> signInWithApple( + String languageCode, + Gender gender, + ) async { + final appleAuth = await _getAppleAuth(); + + final token = await client.postType( + apiConst.loginWithApple, + fromJson: TokenResponse.fromJson, + body: {'access_token': appleAuth.accessToken}, + ); + + return token.fold(Left.new, (r) async { + final user = UserModelResponse( + accessToken: r.key, + username: appleAuth.name, + gender: gender, + localeCode: languageCode, + ); + + await storage.writeString(key: StorageKeys.tokenKey, value: user.accessToken); + + return Right(user); + }); + } + + Future<_UserReqParam> _getAppleAuth() async { + if (isIntegrationTest) { + return const _UserReqParam( + name: 'Test User', + accessToken: r'myquran_te$t_t0ken', + ); + } else { + final appleAuth = await soccialAuth.signInWithApple(); + final accessToken = appleAuth.credential?.accessToken ?? ''; + final username = appleAuth.user?.displayName ?? ''; + return _UserReqParam( + name: username, + accessToken: accessToken, + ); + } + } + + @override + Future> saveUserData(UserEntity userEntity) { + return client.putType( + apiConst.putProfile(userEntity.accessToken), + fromJson: UserDataResponse.fromJson, + body: { + 'gender': userEntity.gender.name.toUpperCase(), + 'language': userEntity.localeCode.toUpperCase(), + }, + ); + } + + @override + Future> pathGender({ + required String userId, + required Gender gender, + }) { + return client.patchType( + apiConst.putProfile(userId), + fromJson: UserDataResponse.fromJson, + body: {'gender': gender.name.toUpperCase()}, + ); + } + + @override + Future> pathLocaleCode({ + required String userId, + required String localeCode, + }) { + return client.patchType( + apiConst.putProfile(userId), + fromJson: UserDataResponse.fromJson, + body: {'language': localeCode.toUpperCase()}, + ); + } + + @override + Future logoutRemote() async { + await soccialAuth.logOut(); + } + + @override + Future> fetchSmsCode({ + required String code, + required String languageCode, + required Gender gender, + }) async { + try { + final token = await client.post( + 'apiConst.fetchSmsCode', + fromJson: TokenResponse.fromJson, + body: {'code': code}, + ); + return token.fold( + (error) { + return Left(error); + }, + (r) async { + final user = UserModelResponse( + accessToken: r.key, + username: '', + gender: gender, + localeCode: languageCode, + ); + + await storage.writeString(key: StorageKeys.tokenKey, value: user.accessToken); + + return Right(user); + }, + ); + } catch (e) { + return Left(Exception('Error fetching SMS code: $e')); + } + } + + @override + Future loginWithEmail(String email) async { + try { + await client.post( + 'apiConst.loginWithEmail', + fromJson: TokenResponse.fromJson, + body: {'email': email}, + ); + } catch (e) { + throw Exception('Error during login: $e'); + } + } +} + +@immutable +final class _UserReqParam { + const _UserReqParam({ + required this.name, + required this.accessToken, + }); + + final String name; + final String accessToken; +} diff --git a/app/lib/app/data/source/theme_local_data_source.dart b/app/lib/app/data/source/theme_local_data_source.dart index 3c33c02e..0ead7590 100644 --- a/app/lib/app/data/source/theme_local_data_source.dart +++ b/app/lib/app/data/source/theme_local_data_source.dart @@ -1,30 +1,7 @@ -import 'package:flutter/material.dart'; -import 'package:my_quran/constants/contants.dart'; -import 'package:mq_storage/mq_storage.dart'; import 'package:my_quran/theme/theme.dart'; -@immutable -final class ThemeLocalDataSource { - const ThemeLocalDataSource(this.storage); - final PreferencesStorage storage; - - CustomTheme get initialTheme { - final isDark = storage.readBool(key: StorageKeys.modeKey); - final cachedColorIndex = storage.readInt(key: StorageKeys.colorKey); - final brightness = isDark != null ? (isDark ? Brightness.dark : Brightness.light) : Brightness.light; - final targetColor = _getColor(cachedColorIndex); - return CustomTheme(brightness, targetColor); - } - - Future saveThemePrimaryColor(int index) async { - await storage.writeInt(key: StorageKeys.colorKey, value: index); - } - - Future saveThemeMode({required bool isDark}) async { - await storage.writeBool(key: StorageKeys.modeKey, value: isDark); - } - - Color _getColor(int? cacheColor) { - return TargetColor.fromIndex(cacheColor ?? 0).color; - } +abstract class ThemeLocalDataSource { + CustomTheme get initialTheme; + Future saveThemePrimaryColor(int index); + Future saveThemeMode({required bool isDark}); } diff --git a/app/lib/app/domain/entity/user_data_entity.dart b/app/lib/app/domain/entity/user_data_entity.dart index aeb007ee..ea04b375 100644 --- a/app/lib/app/domain/entity/user_data_entity.dart +++ b/app/lib/app/domain/entity/user_data_entity.dart @@ -11,9 +11,7 @@ final class UserDataEntity { final String gender; final String language; - Gender get genderValue { - return gender.toLowerCase() == 'male' ? Gender.male : Gender.female; - } + Gender get genderValue => Gender.fromData(gender.toLowerCase()); String get localeValue => language.toLowerCase(); } diff --git a/app/lib/app/domain/entity/user_entity.dart b/app/lib/app/domain/entity/user_entity.dart index d4e3c168..88dd9952 100644 --- a/app/lib/app/domain/entity/user_entity.dart +++ b/app/lib/app/domain/entity/user_entity.dart @@ -29,4 +29,15 @@ final class UserEntity { } } -enum Gender { male, female } +enum Gender { + male, + female; + + factory Gender.fromData(String? src) { + return switch (src) { + 'male' => Gender.male, + 'female' => Gender.female, + _ => Gender.male, + }; + } +} diff --git a/app/lib/app/presentation/view/app_view.dart b/app/lib/app/presentation/view/app_view.dart index e2522852..94d38484 100644 --- a/app/lib/app/presentation/view/app_view.dart +++ b/app/lib/app/presentation/view/app_view.dart @@ -17,18 +17,21 @@ class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { + final isMockData = context.read().isMockData; return MultiBlocProvider( providers: [ RepositoryProvider( create: (context) => AppRepositoryImpl( - AppLocalDataSource( - packageInfo: context.read(), - ), + isMockData + ? const AppLocalDataSourceMock() + : AppLocalDataSourceImpl(packageInfo: context.read()), ), ), RepositoryProvider( create: (context) => ThemeRepositoryImpl( - ThemeLocalDataSource(context.read()), + isMockData + ? const ThemeLocalDataSourceMock() + : ThemeLocalDataSourceImpl(context.read()), ), ), BlocProvider( @@ -40,17 +43,21 @@ class MyApp extends StatelessWidget { ), ), RepositoryProvider( - create: (context) => AuthRepositoryImpl( - localDataSource: AuthLocalDataSource( - context.read(), - ), - remoteDataSource: AuthRemoteDataSource( - client: context.read(), - storage: context.read(), - soccialAuth: context.read(), - isIntegrationTest: context.read().isIntegrationTest, - ), - ), + create: (context) { + return AuthRepositoryImpl( + localDataSource: isMockData + ? const AuthLocalDataSourceMock() + : AuthLocalDataSourceImpl(context.read()), + remoteDataSource: isMockData + ? const AuthRemoteDataSourceMock() + : AuthRemoteDataSourceImpl( + client: context.read(), + storage: context.read(), + soccialAuth: context.read(), + isIntegrationTest: context.read().isIntegrationTest, + ), + ); + }, ), BlocProvider( create: (context) => AuthCubit( diff --git a/app/lib/config/app_config.dart b/app/lib/config/app_config.dart index 81c66e0d..3b335e3a 100644 --- a/app/lib/config/app_config.dart +++ b/app/lib/config/app_config.dart @@ -7,9 +7,11 @@ final class AppConfig { const AppConfig({ this.storage, this.isIntegrationTest = false, + this.isMockData = false, }); final bool isIntegrationTest; + final bool isMockData; final PreferencesStorage? storage; diff --git a/app/test/widget_test.dart b/app/test/widget_test.dart index 7b154882..0b864e79 100644 --- a/app/test/widget_test.dart +++ b/app/test/widget_test.dart @@ -17,12 +17,12 @@ void main() { final remoteConfig = MockMqRemoteConfig(); final homeRepo = MockHomeRepositoryImpl(); - final appLocalDataSource = AppLocalDataSource(packageInfo: packageInfo); + final appLocalDataSource = AppLocalDataSourceImpl(packageInfo: packageInfo); final appRepository = AppRepositoryImpl(appLocalDataSource); - final themeRepository = ThemeRepositoryImpl(ThemeLocalDataSource(storage)); + final themeRepository = ThemeRepositoryImpl(ThemeLocalDataSourceImpl(storage)); final authRepository = AuthRepositoryImpl( - localDataSource: AuthLocalDataSource(storage), - remoteDataSource: AuthRemoteDataSource( + localDataSource: AuthLocalDataSourceImpl(storage), + remoteDataSource: AuthRemoteDataSourceImpl( client: remoteClient, storage: storage, soccialAuth: MockSccialAuth(),