diff --git a/assets/images/error.png b/assets/images/error.png new file mode 100644 index 0000000..dd3b679 Binary files /dev/null and b/assets/images/error.png differ diff --git a/lib/common_ui/resources/my_assets.dart b/lib/common_ui/resources/my_assets.dart index 063d962..2f9b9c9 100644 --- a/lib/common_ui/resources/my_assets.dart +++ b/lib/common_ui/resources/my_assets.dart @@ -38,4 +38,5 @@ class MyAssets { static const String homeButton = 'assets/images/home_button.png'; static const String doneRounded = 'assets/images/done_rounded.svg'; static const String lang = 'assets/images/lang.svg'; + static const String error = 'assets/images/error.png'; } \ No newline at end of file diff --git a/lib/common_ui/resources/my_text_style.dart b/lib/common_ui/resources/my_text_style.dart index 1d93190..8b4f29e 100644 --- a/lib/common_ui/resources/my_text_style.dart +++ b/lib/common_ui/resources/my_text_style.dart @@ -18,6 +18,11 @@ class DinoKids { fontSize: 26, fontWeight: FontWeight.w400, ); + static const TextStyle regular35 = TextStyle( + fontFamily: fontFamily, + fontSize: 35, + fontWeight: FontWeight.w400, + ); static const TextStyle regular45 = TextStyle( fontFamily: fontFamily, fontSize: 45, @@ -43,6 +48,11 @@ class Marhey { fontSize: 16, fontWeight: FontWeight.w500, ); + static const TextStyle medium22 = TextStyle( + fontFamily: fontFamily, + fontSize: 22, + fontWeight: FontWeight.w500, + ); /// Semi Bold static const TextStyle semiBold17 = TextStyle( diff --git a/lib/common_ui/theme/my_theme.dart b/lib/common_ui/theme/my_theme.dart index 9df4d3e..1223ae8 100644 --- a/lib/common_ui/theme/my_theme.dart +++ b/lib/common_ui/theme/my_theme.dart @@ -1,8 +1,7 @@ -import 'package:hadi_hoda_flutter/core/utils/context_provider.dart'; import 'package:flutter/material.dart'; import 'package:hadi_hoda_flutter/common_ui/resources/my_colors.dart'; -enum ColorsName { primaryColor, noColor, backgroundDialog } +enum ColorsName { primaryColor, backgroundDialog } class MyTheme { static const MyTheme _i = MyTheme._internal(); @@ -14,25 +13,12 @@ class MyTheme { static final ThemeData dark = ThemeData(brightness: Brightness.dark); static Map get lightColors => { - ColorsName.noColor: MyColors.transparent, ColorsName.primaryColor: MyColors.white, ColorsName.backgroundDialog: MyColors.purple, }; static Map get darkColors => { - ColorsName.noColor: MyColors.transparent, ColorsName.primaryColor: MyColors.black, ColorsName.backgroundDialog: MyColors.purple, }; -} - -extension ThemeExtension on BuildContext { - Map get customColors => - Theme.of(ContextProvider.context!).brightness == Brightness.dark - ? MyTheme.darkColors - : MyTheme.lightColors; - - Color get primaryColor => customColors[ColorsName.primaryColor]!; - Color get noColor => customColors[ColorsName.noColor]!; - Color get backgroundDialog => customColors[ColorsName.backgroundDialog]!; -} +} \ No newline at end of file diff --git a/lib/core/constants/my_constants.dart b/lib/core/constants/my_constants.dart index e96b59e..76b8d54 100644 --- a/lib/core/constants/my_constants.dart +++ b/lib/core/constants/my_constants.dart @@ -9,4 +9,5 @@ class MyConstants { static const String downloadCompleted = 'DOWNLOAD_COMPLETED'; static const String extractCompleted = 'EXTRACT_COMPLETED'; static const String selectLanguage = 'SELECT_LANGUAGE'; + static const String firstLanguagePage = 'FIRST_LANGUAGE_PAGE'; } \ No newline at end of file diff --git a/lib/core/middleware/language_middleware.dart b/lib/core/middleware/language_middleware.dart deleted file mode 100644 index 3d092bd..0000000 --- a/lib/core/middleware/language_middleware.dart +++ /dev/null @@ -1,21 +0,0 @@ -import 'dart:async'; - -import 'package:flutter/material.dart'; -import 'package:hadi_hoda_flutter/core/constants/my_constants.dart'; -import 'package:hadi_hoda_flutter/core/routers/my_routes.dart'; -import 'package:go_router/go_router.dart'; -import 'package:hadi_hoda_flutter/core/utils/local_storage.dart'; - -class LanguageMiddleware { - static const LanguageMiddleware _i = LanguageMiddleware._internal(); - const LanguageMiddleware._internal(); - factory LanguageMiddleware() => _i; - - static FutureOr redirect(BuildContext context, GoRouterState state) async { - if (LocalStorage.readData(key: MyConstants.selectLanguage).isNotEmpty) { - return Routes.homePage; - } else { - return null; - } - } -} diff --git a/lib/core/params/language_params.dart b/lib/core/params/language_params.dart index c5866ec..7e926b1 100644 --- a/lib/core/params/language_params.dart +++ b/lib/core/params/language_params.dart @@ -11,7 +11,7 @@ class LanguageParams { ); } - Map get toHeader => { - if (code != null) 'HTTP_X_USER_LANGUAGE': code, + Map get toQuery => { + if (code != null) 'lang': code, }; } diff --git a/lib/core/routers/my_routes.dart b/lib/core/routers/my_routes.dart index 5066c81..13f5e6b 100644 --- a/lib/core/routers/my_routes.dart +++ b/lib/core/routers/my_routes.dart @@ -1,12 +1,12 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:go_router/go_router.dart'; -import 'package:hadi_hoda_flutter/core/middleware/language_middleware.dart'; import 'package:hadi_hoda_flutter/core/utils/context_provider.dart'; import 'package:hadi_hoda_flutter/features/home/presentation/bloc/home_bloc.dart'; import 'package:hadi_hoda_flutter/features/home/presentation/ui/home_page.dart'; import 'package:hadi_hoda_flutter/features/intro/presentation/bloc/intro_bloc.dart'; import 'package:hadi_hoda_flutter/features/intro/presentation/ui/intro_page.dart'; import 'package:hadi_hoda_flutter/features/language/presentation/bloc/language_bloc.dart'; +import 'package:hadi_hoda_flutter/features/language/presentation/bloc/language_event.dart'; import 'package:hadi_hoda_flutter/features/language/presentation/ui/language_page.dart'; import 'package:hadi_hoda_flutter/features/level/presentation/bloc/level_bloc.dart'; import 'package:hadi_hoda_flutter/features/level/presentation/bloc/level_event.dart'; @@ -36,16 +36,15 @@ GoRouter get appPages => GoRouter( name: Routes.introPage, path: Routes.introPage, builder: (context, state) => BlocProvider( - create: (context) => IntroBloc(locator(), locator()), + create: (context) => IntroBloc(locator(), locator(), locator()), child: const IntroPage(), ), ), GoRoute( name: Routes.languagePage, path: Routes.languagePage, - redirect: LanguageMiddleware.redirect, builder: (context, state) => BlocProvider( - create: (context) => LanguageBloc(locator()), + create: (context) => LanguageBloc()..add(InitLanguageEvent()), child: const LanguagePage(), ), ), diff --git a/lib/core/utils/context_provider.dart b/lib/core/utils/context_provider.dart index e92a900..f7d5724 100644 --- a/lib/core/utils/context_provider.dart +++ b/lib/core/utils/context_provider.dart @@ -6,5 +6,5 @@ class ContextProvider { factory ContextProvider() => _i; static GlobalKey navigatorKey = GlobalKey(); - static BuildContext? context = navigatorKey.currentContext; + static BuildContext context = navigatorKey.currentContext!; } diff --git a/lib/core/utils/convert_size.dart b/lib/core/utils/convert_size.dart new file mode 100644 index 0000000..0a114d9 --- /dev/null +++ b/lib/core/utils/convert_size.dart @@ -0,0 +1,5 @@ +extension ConvertSize on double? { + String get toMB { + return this == null ? '0.0' : (this! / (1024 * 1024)).toStringAsFixed(1); + } +} diff --git a/lib/core/utils/my_image.dart b/lib/core/utils/my_image.dart index 586b81c..bf977e3 100644 --- a/lib/core/utils/my_image.dart +++ b/lib/core/utils/my_image.dart @@ -1,6 +1,5 @@ import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; -import 'package:hadi_hoda_flutter/common_ui/theme/my_theme.dart'; class MyImage extends StatelessWidget { const MyImage({ @@ -32,7 +31,7 @@ class MyImage extends StatelessWidget { width: size, height: size, colorFilter: color != null - ? ColorFilter.mode(color ?? context.primaryColor, BlendMode.srcIn) + ? ColorFilter.mode(color!, BlendMode.srcIn) : null, ); } diff --git a/lib/core/widgets/about_us_dialog/about_us_dialog.dart b/lib/core/widgets/about_us_dialog/about_us_dialog.dart index 0817498..a982547 100644 --- a/lib/core/widgets/about_us_dialog/about_us_dialog.dart +++ b/lib/core/widgets/about_us_dialog/about_us_dialog.dart @@ -3,8 +3,8 @@ import 'dart:ui'; import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:hadi_hoda_flutter/common_ui/resources/my_assets.dart'; +import 'package:hadi_hoda_flutter/common_ui/resources/my_colors.dart'; import 'package:hadi_hoda_flutter/common_ui/resources/my_text_style.dart'; -import 'package:hadi_hoda_flutter/common_ui/theme/my_theme.dart'; import 'package:hadi_hoda_flutter/core/utils/check_platform.dart'; import 'package:hadi_hoda_flutter/core/utils/my_image.dart'; import 'package:hadi_hoda_flutter/core/utils/my_localization.dart'; @@ -14,7 +14,7 @@ Future showAboutUsDialog({required BuildContext context}) async { await showDialog( context: context, builder: (context) => AboutUsDialog(), - barrierColor: context.backgroundDialog.withValues(alpha: 0.82), + barrierColor: MyColors.purple.withValues(alpha: 0.82), useSafeArea: false, ); } @@ -25,7 +25,7 @@ class AboutUsDialog extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( - backgroundColor: context.noColor, + backgroundColor: MyColors.transparent, body: BackdropFilter( filter: ImageFilter.blur(sigmaX: 6, sigmaY: 6), child: Center( diff --git a/lib/core/widgets/answer_box/styles/picture_box.dart b/lib/core/widgets/answer_box/styles/picture_box.dart index bef6f28..6609a71 100644 --- a/lib/core/widgets/answer_box/styles/picture_box.dart +++ b/lib/core/widgets/answer_box/styles/picture_box.dart @@ -1,9 +1,9 @@ import 'dart:io'; import 'package:flutter/material.dart'; +import 'package:hadi_hoda_flutter/common_ui/resources/my_colors.dart'; import 'package:hadi_hoda_flutter/common_ui/resources/my_spaces.dart'; import 'package:hadi_hoda_flutter/common_ui/resources/my_text_style.dart'; -import 'package:hadi_hoda_flutter/common_ui/theme/my_theme.dart'; class AnswerPictureBox extends StatelessWidget { const AnswerPictureBox({super.key, required this.selected, required this.image, required this.index}); @@ -49,7 +49,7 @@ class AnswerPictureBox extends StatelessWidget { child: Text( '$index', style: Marhey.semiBold17.copyWith( - color: context.primaryColor, + color: MyColors.white, ), ), ), diff --git a/lib/core/widgets/button/my_button.dart b/lib/core/widgets/button/my_button.dart index 188cb3a..a0b48fd 100644 --- a/lib/core/widgets/button/my_button.dart +++ b/lib/core/widgets/button/my_button.dart @@ -1,8 +1,8 @@ import 'package:flutter/material.dart'; import 'package:hadi_hoda_flutter/common_ui/resources/my_assets.dart'; +import 'package:hadi_hoda_flutter/common_ui/resources/my_colors.dart'; import 'package:hadi_hoda_flutter/common_ui/resources/my_spaces.dart'; import 'package:hadi_hoda_flutter/common_ui/resources/my_text_style.dart'; -import 'package:hadi_hoda_flutter/common_ui/theme/my_theme.dart'; import 'package:hadi_hoda_flutter/core/utils/my_image.dart'; import 'package:hadi_hoda_flutter/core/widgets/button/enum/button_type.dart'; @@ -25,8 +25,8 @@ class MyButton extends StatelessWidget { width: 194, child: InkWell( onTap: onTap, - highlightColor: context.noColor, - splashColor: context.noColor, + highlightColor: MyColors.transparent, + splashColor: MyColors.transparent, child: Stack( alignment: Alignment.center, children: [ diff --git a/lib/core/widgets/error/error_state.dart b/lib/core/widgets/error/error_state.dart new file mode 100644 index 0000000..d39e965 --- /dev/null +++ b/lib/core/widgets/error/error_state.dart @@ -0,0 +1,59 @@ +import 'package:flutter/material.dart'; +import 'package:hadi_hoda_flutter/common_ui/resources/my_assets.dart'; +import 'package:hadi_hoda_flutter/common_ui/resources/my_colors.dart'; +import 'package:hadi_hoda_flutter/common_ui/resources/my_spaces.dart'; +import 'package:hadi_hoda_flutter/common_ui/resources/my_text_style.dart'; +import 'package:hadi_hoda_flutter/core/utils/gap.dart'; +import 'package:hadi_hoda_flutter/core/utils/my_image.dart'; +import 'package:hadi_hoda_flutter/core/utils/my_localization.dart'; + +class ErrorState extends StatelessWidget { + const ErrorState({super.key, this.onTap}); + + final VoidCallback? onTap; + + @override + Widget build(BuildContext context) { + return Column( + children: [ + Spacer(), + Text( + context.translate.lost_connection, + style: DinoKids.regular45.copyWith(color: MyColors.white), + ), + MyImage(image: MyAssets.error), + MySpaces.s40.gapHeight, + Text( + context.translate.connected_to_internet, + textAlign: TextAlign.center, + style: Marhey.medium12.copyWith(color: MyColors.white), + ), + Spacer(), + SizedBox( + height: 84, + width: 194, + child: InkWell( + onTap: onTap, + highlightColor: MyColors.transparent, + splashColor: MyColors.transparent, + child: Stack( + alignment: Alignment.center, + children: [ + MyImage(image: MyAssets.button), + PositionedDirectional( + top: MySpaces.s8, + child: Text( + context.translate.try_again, + style: DinoKids.regular35.copyWith( + color: Color(0XFF1D6EFF), + ), + ), + ), + ], + ), + ), + ), + ], + ); + } +} diff --git a/lib/core/widgets/showcase/question_showcase.dart b/lib/core/widgets/showcase/question_showcase.dart index efc1c2a..79c4f5b 100644 --- a/lib/core/widgets/showcase/question_showcase.dart +++ b/lib/core/widgets/showcase/question_showcase.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:hadi_hoda_flutter/common_ui/resources/my_assets.dart'; +import 'package:hadi_hoda_flutter/common_ui/resources/my_colors.dart'; import 'package:hadi_hoda_flutter/common_ui/resources/my_text_style.dart'; -import 'package:hadi_hoda_flutter/common_ui/theme/my_theme.dart'; import 'package:hadi_hoda_flutter/core/utils/my_image.dart'; import 'package:hadi_hoda_flutter/core/utils/screen_size.dart'; import 'package:showcaseview/showcaseview.dart'; @@ -26,10 +26,10 @@ class QuestionShowcase extends StatelessWidget { targetShapeBorder: CircleBorder(), tooltipBackgroundColor: Colors.transparent, disableMovingAnimation: true, - textColor: context.primaryColor, + textColor: MyColors.white, descriptionTextAlign: TextAlign.center, descTextStyle: Marhey.bold12.copyWith( - color: context.primaryColor, + color: MyColors.white, ), disableScaleAnimation: true, tooltipPadding: EdgeInsets.only(top: 60), diff --git a/lib/features/home/presentation/bloc/home_bloc.dart b/lib/features/home/presentation/bloc/home_bloc.dart index 114736f..7360c97 100644 --- a/lib/features/home/presentation/bloc/home_bloc.dart +++ b/lib/features/home/presentation/bloc/home_bloc.dart @@ -29,6 +29,10 @@ class HomeBloc extends Bloc { context.pushNamed(Routes.levelPage); } + void goToLanguagePage(BuildContext context){ + context.pushNamed(Routes.languagePage); + } + /// ------------Api Calls------------ FutureOr _getHomeEvent(event, emit) async { await _getHomeUseCase(event.homeParams).then( diff --git a/lib/features/home/presentation/ui/home_page.dart b/lib/features/home/presentation/ui/home_page.dart index 82c5c85..17472af 100644 --- a/lib/features/home/presentation/ui/home_page.dart +++ b/lib/features/home/presentation/ui/home_page.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:hadi_hoda_flutter/common_ui/resources/my_assets.dart'; -import 'package:hadi_hoda_flutter/common_ui/theme/my_theme.dart'; +import 'package:hadi_hoda_flutter/common_ui/resources/my_colors.dart'; import 'package:hadi_hoda_flutter/core/utils/check_platform.dart'; import 'package:hadi_hoda_flutter/core/utils/my_image.dart'; import 'package:hadi_hoda_flutter/core/utils/screen_size.dart'; @@ -13,7 +13,7 @@ class HomePage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar(backgroundColor: context.noColor), + appBar: AppBar(backgroundColor: MyColors.transparent), extendBodyBehindAppBar: true, body: DecoratedBox( decoration: BoxDecoration( @@ -70,9 +70,12 @@ class HomePage extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - MyImage( - image: MyAssets.language, - size: checkSize(context: context, tablet: 120), + InkWell( + onTap: () => context.read().goToLanguagePage(context), + child: MyImage( + image: MyAssets.language, + size: checkSize(context: context, tablet: 120), + ), ), InkWell( child: MyImage( diff --git a/lib/features/intro/data/datasource/intro_datasource.dart b/lib/features/intro/data/datasource/intro_datasource.dart index 15d4a31..d43a046 100644 --- a/lib/features/intro/data/datasource/intro_datasource.dart +++ b/lib/features/intro/data/datasource/intro_datasource.dart @@ -6,31 +6,48 @@ import 'package:hadi_hoda_flutter/core/constants/my_api.dart'; import 'package:hadi_hoda_flutter/core/constants/my_constants.dart'; import 'package:hadi_hoda_flutter/core/error_handler/my_exception.dart'; import 'package:hadi_hoda_flutter/core/network/http_request.dart'; +import 'package:hadi_hoda_flutter/core/response/base_response.dart'; import 'package:hadi_hoda_flutter/core/utils/local_storage.dart'; import 'package:hadi_hoda_flutter/core/utils/storage_path.dart'; +import 'package:hadi_hoda_flutter/features/intro/domain/entities/download_entity.dart'; +import 'package:hadi_hoda_flutter/features/level/data/model/level_model.dart'; +import 'package:hadi_hoda_flutter/features/level/domain/entity/level_entity.dart'; +import 'package:hadi_hoda_flutter/features/level/domain/entity/total_data_entity.dart'; +import 'package:hive/hive.dart'; abstract class IIntroDatasource { Future getFiles(); - Stream loadingStream(); + Future saveLevels(); + Stream loadingStream(); } class IntroDatasourceImpl implements IIntroDatasource { final IHttpRequest httpRequest; - final StreamController streamController = StreamController.broadcast(); + final StreamController streamController = StreamController.broadcast(); IntroDatasourceImpl(this.httpRequest); @override Future getFiles() async { final String filePath = '${StoragePath.documentDir.path}/files.zip'; + final String selectedLanguage = + LocalStorage.readData(key: MyConstants.selectLanguage).isEmpty + ? 'fa' + : LocalStorage.readData(key: MyConstants.selectLanguage); if (LocalStorage.readData(key: MyConstants.downloadCompleted) != 'true') { await httpRequest.download( urlPath: MyApi.files, savePath: filePath, + queryParameters: { + 'lang': selectedLanguage, + }, onReceive: (count, total) { - double percent = ((count / total) * 100); - streamController.add(percent); + streamController.add(DownloadEntity( + count: count / 1, + total: total / 1, + percent: (count / total) * 100, + )); }, ).then((value) async { await LocalStorage.saveData( @@ -43,12 +60,11 @@ class IntroDatasourceImpl implements IIntroDatasource { try{ if (LocalStorage.readData(key: MyConstants.extractCompleted) != 'true') { final File file = File(filePath); - final Directory directory = Directory('${StoragePath.documentDir.path}/files/'); + final Directory directory = Directory('${StoragePath.documentDir.path}/$selectedLanguage/files/'); await ZipFile.extractToDirectory( zipFile: file, destinationDir: directory, onExtracting: (zipEntry, progress) { - streamController.add(progress); return ZipFileOperation.includeItem; }, ).then((value) async { @@ -61,9 +77,9 @@ class IntroDatasourceImpl implements IIntroDatasource { ]); }); } else { - streamController.add(50); + streamController.add(DownloadEntity(percent: 50)); await Future.delayed(Duration(milliseconds: 150)); - streamController.add(100); + streamController.add(DownloadEntity(percent: 100)); } } catch (e){ throw MyException(errorMessage: '$e'); @@ -71,5 +87,32 @@ class IntroDatasourceImpl implements IIntroDatasource { } @override - Stream loadingStream() => streamController.stream; + Future saveLevels() async { + final String selectedLanguage = + LocalStorage.readData(key: MyConstants.selectLanguage).isEmpty + ? 'fa' + : LocalStorage.readData(key: MyConstants.selectLanguage); + final Box data = Hive.box(MyConstants.levelBox); + final TotalDataEntity findData = data.values.singleWhere( + (e) => e.code == selectedLanguage, + orElse: () => TotalDataEntity(), + ); + + if (findData.code != selectedLanguage) { + final response = await httpRequest.get( + path: MyApi.levels, + queryParameters: {'lang': selectedLanguage}, + ); + final List levels = BaseResponse.getDataList( + response?['result'], + (json) => LevelModel.fromJson(json), + ); + await Future.wait([ + data.add(TotalDataEntity(code: selectedLanguage, levels: levels)), + ]); + } + } + + @override + Stream loadingStream() => streamController.stream; } diff --git a/lib/features/intro/data/repository_impl/intro_repository_impl.dart b/lib/features/intro/data/repository_impl/intro_repository_impl.dart index 9dfa48c..fbae565 100644 --- a/lib/features/intro/data/repository_impl/intro_repository_impl.dart +++ b/lib/features/intro/data/repository_impl/intro_repository_impl.dart @@ -3,6 +3,7 @@ import 'package:hadi_hoda_flutter/core/error_handler/my_exception.dart'; import 'package:hadi_hoda_flutter/core/params/no_params.dart'; import 'package:hadi_hoda_flutter/core/utils/data_state.dart'; import 'package:hadi_hoda_flutter/features/intro/data/datasource/intro_datasource.dart'; +import 'package:hadi_hoda_flutter/features/intro/domain/entities/download_entity.dart'; import 'package:hadi_hoda_flutter/features/intro/domain/repository/intro_repository.dart'; class IntroRepositoryImpl implements IIntroRepository { @@ -27,7 +28,23 @@ class IntroRepositoryImpl implements IIntroRepository { } @override - Stream loadingStream() { + Future> saveLevels() async { + try { + await datasource.saveLevels(); + return DataState.success(NoParams()); + } on MyException catch (e) { + return DataState.error(e); + } catch (e) { + if (kDebugMode) { + rethrow; + } else { + return DataState.error(MyException(errorMessage: '$e')); + } + } + } + + @override + Stream loadingStream() { return datasource.loadingStream(); } } diff --git a/lib/features/intro/domain/entities/download_entity.dart b/lib/features/intro/domain/entities/download_entity.dart new file mode 100644 index 0000000..589fd5a --- /dev/null +++ b/lib/features/intro/domain/entities/download_entity.dart @@ -0,0 +1,7 @@ +class DownloadEntity { + final double? count; + final double? total; + final double? percent; + + const DownloadEntity({this.count, this.total, this.percent}); +} diff --git a/lib/features/intro/domain/repository/intro_repository.dart b/lib/features/intro/domain/repository/intro_repository.dart index 717feb4..adb6554 100644 --- a/lib/features/intro/domain/repository/intro_repository.dart +++ b/lib/features/intro/domain/repository/intro_repository.dart @@ -1,8 +1,10 @@ import 'package:hadi_hoda_flutter/core/error_handler/my_exception.dart'; import 'package:hadi_hoda_flutter/core/params/no_params.dart'; import 'package:hadi_hoda_flutter/core/utils/data_state.dart'; +import 'package:hadi_hoda_flutter/features/intro/domain/entities/download_entity.dart'; abstract class IIntroRepository { Future> getFiles(); - Stream loadingStream(); + Future> saveLevels(); + Stream loadingStream(); } diff --git a/lib/features/intro/domain/usecases/loading_stream_usecase.dart b/lib/features/intro/domain/usecases/loading_stream_usecase.dart index a24d6ed..5c44199 100644 --- a/lib/features/intro/domain/usecases/loading_stream_usecase.dart +++ b/lib/features/intro/domain/usecases/loading_stream_usecase.dart @@ -1,3 +1,4 @@ +import 'package:hadi_hoda_flutter/features/intro/domain/entities/download_entity.dart'; import 'package:hadi_hoda_flutter/features/intro/domain/repository/intro_repository.dart'; class LoadingStreamUseCase { @@ -5,7 +6,7 @@ class LoadingStreamUseCase { const LoadingStreamUseCase(this.repository); - Stream call() { + Stream call() { return repository.loadingStream(); } } diff --git a/lib/features/intro/domain/usecases/save_levels_usecase.dart b/lib/features/intro/domain/usecases/save_levels_usecase.dart new file mode 100644 index 0000000..87f385b --- /dev/null +++ b/lib/features/intro/domain/usecases/save_levels_usecase.dart @@ -0,0 +1,16 @@ +import 'package:hadi_hoda_flutter/core/error_handler/my_exception.dart'; +import 'package:hadi_hoda_flutter/core/params/no_params.dart'; +import 'package:hadi_hoda_flutter/core/usecase/usecase.dart'; +import 'package:hadi_hoda_flutter/core/utils/data_state.dart'; +import 'package:hadi_hoda_flutter/features/intro/domain/repository/intro_repository.dart'; + +class SaveLevelsUseCase implements UseCase { + final IIntroRepository repository; + + const SaveLevelsUseCase(this.repository); + + @override + Future> call(NoParams params) { + return repository.saveLevels(); + } +} diff --git a/lib/features/intro/presentation/bloc/intro_bloc.dart b/lib/features/intro/presentation/bloc/intro_bloc.dart index 26fbddd..8ff8483 100644 --- a/lib/features/intro/presentation/bloc/intro_bloc.dart +++ b/lib/features/intro/presentation/bloc/intro_bloc.dart @@ -2,29 +2,39 @@ import 'dart:async'; import 'package:bloc/bloc.dart'; import 'package:go_router/go_router.dart'; +import 'package:hadi_hoda_flutter/core/constants/my_constants.dart'; import 'package:hadi_hoda_flutter/core/params/no_params.dart'; import 'package:hadi_hoda_flutter/core/routers/my_routes.dart'; import 'package:hadi_hoda_flutter/core/status/base_status.dart'; import 'package:hadi_hoda_flutter/core/utils/context_provider.dart'; +import 'package:hadi_hoda_flutter/core/utils/local_storage.dart'; +import 'package:hadi_hoda_flutter/features/intro/domain/entities/download_entity.dart'; import 'package:hadi_hoda_flutter/features/intro/domain/usecases/get_files_usecase.dart'; import 'package:hadi_hoda_flutter/features/intro/domain/usecases/loading_stream_usecase.dart'; +import 'package:hadi_hoda_flutter/features/intro/domain/usecases/save_levels_usecase.dart'; import 'package:hadi_hoda_flutter/features/intro/presentation/bloc/intro_event.dart'; import 'package:hadi_hoda_flutter/features/intro/presentation/bloc/intro_state.dart'; class IntroBloc extends Bloc { /// ------------constructor------------ - IntroBloc(this._getFilesUseCase, this._loadingStreamUseCase) + IntroBloc( + this._getFilesUseCase, + this._loadingStreamUseCase, + this._saveLevelsUseCase, + ) : super(const IntroState()) { on(_getFilesEvent); + on(_saveLevelsEvent); loadingStream = _loadingStreamUseCase(); } /// ------------UseCases------------ final GetFilesUseCase _getFilesUseCase; + final SaveLevelsUseCase _saveLevelsUseCase; final LoadingStreamUseCase _loadingStreamUseCase; /// ------------Variables------------ - Stream loadingStream = Stream.empty(); + Stream loadingStream = Stream.empty(); /// ------------Controllers------------ @@ -35,19 +45,38 @@ class IntroBloc extends Bloc { GetFilesEvent event, Emitter emit, ) async { + emit(state.copyWith(getFilesStatus: BaseInit())); await _getFilesUseCase(NoParams()).then((value) { value.fold( (data) async { - await Future.delayed( - Duration(milliseconds: 300), () { - ContextProvider.context!.goNamed(Routes.languagePage); - }, - ); + add(SaveLevelsEvent()); }, - (error) { + (error) async { emit(state.copyWith(getFilesStatus: BaseError(error.errorMessage))); }, ); }); } + + FutureOr _saveLevelsEvent(SaveLevelsEvent event, + Emitter emit) async { + await _saveLevelsUseCase(NoParams()).then((value) => + value.fold( + (data) async { + if(LocalStorage.readData(key: MyConstants.firstLanguagePage) != 'true'){ + ContextProvider.context.goNamed(Routes.languagePage); + } else { + await Future.delayed(Duration(milliseconds: 500), () { + if (ContextProvider.context.mounted) { + ContextProvider.context.goNamed(Routes.homePage); + } + }); + } + }, + (error) { + emit(state.copyWith(getFilesStatus: BaseError(error.errorMessage))); + }, + ), + ); + } } diff --git a/lib/features/intro/presentation/bloc/intro_event.dart b/lib/features/intro/presentation/bloc/intro_event.dart index 70e23cc..271b2a0 100644 --- a/lib/features/intro/presentation/bloc/intro_event.dart +++ b/lib/features/intro/presentation/bloc/intro_event.dart @@ -2,3 +2,4 @@ sealed class IntroEvent { const IntroEvent(); } class GetFilesEvent extends IntroEvent {} +class SaveLevelsEvent extends IntroEvent {} diff --git a/lib/features/intro/presentation/ui/intro_page.dart b/lib/features/intro/presentation/ui/intro_page.dart index b874119..bec6972 100644 --- a/lib/features/intro/presentation/ui/intro_page.dart +++ b/lib/features/intro/presentation/ui/intro_page.dart @@ -1,11 +1,19 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:hadi_hoda_flutter/common_ui/resources/my_assets.dart'; +import 'package:hadi_hoda_flutter/common_ui/resources/my_colors.dart'; import 'package:hadi_hoda_flutter/common_ui/resources/my_spaces.dart'; +import 'package:hadi_hoda_flutter/common_ui/resources/my_text_style.dart'; +import 'package:hadi_hoda_flutter/core/status/base_status.dart'; +import 'package:hadi_hoda_flutter/core/utils/convert_size.dart'; import 'package:hadi_hoda_flutter/core/utils/my_image.dart'; +import 'package:hadi_hoda_flutter/core/utils/my_localization.dart'; import 'package:hadi_hoda_flutter/core/utils/screen_size.dart'; +import 'package:hadi_hoda_flutter/core/widgets/error/error_state.dart'; +import 'package:hadi_hoda_flutter/features/intro/domain/entities/download_entity.dart'; import 'package:hadi_hoda_flutter/features/intro/presentation/bloc/intro_bloc.dart'; import 'package:hadi_hoda_flutter/features/intro/presentation/bloc/intro_event.dart'; +import 'package:hadi_hoda_flutter/features/intro/presentation/bloc/intro_state.dart'; import 'package:hadi_hoda_flutter/features/intro/presentation/ui/widgets/intro_loading_widget.dart'; class IntroPage extends StatefulWidget { @@ -47,12 +55,31 @@ class _IntroPageState extends State { ), ), ), - child: Stack( - alignment: Alignment.center, - children: [ - _image(), - _loading(context), - ], + child: BlocBuilder( + buildWhen: (previous, current) => + previous.getFilesStatus != current.getFilesStatus, + builder: (context, state) { + if (state.getFilesStatus is BaseError) { + return Padding( + padding: EdgeInsets.symmetric( + vertical: MediaQuery.viewPaddingOf(context).bottom + MySpaces.s16, + horizontal: 60, + ), + child: ErrorState( + onTap: () => context.read().add(GetFilesEvent()), + ), + ); + } else { + return Stack( + alignment: Alignment.center, + children: [ + _image(), + _text(context), + _loading(context), + ], + ); + } + } ), ), ); @@ -65,6 +92,33 @@ class _IntroPageState extends State { ); } + Widget _text(BuildContext context) { + return PositionedDirectional( + bottom: 130, + child: Column( + spacing: MySpaces.s6, + children: [ + Text( + context.translate.please_wait, + style: Marhey.medium22.copyWith( + color: MyColors.white, + ), + ), + StreamBuilder( + initialData: DownloadEntity(), + stream: context.read().loadingStream, + builder: (context, snapshot) => Text( + '${context.translate.downloading_data} (${snapshot.data?.count.toMB ?? 0.0}mb / ${snapshot.data?.total.toMB ?? 0.0}mb)', + style: Marhey.medium12.copyWith( + color: MyColors.white, + ), + ), + ), + ], + ), + ); + } + Positioned _loading(BuildContext context) { return Positioned( bottom: MediaQuery.viewPaddingOf(context).bottom + MySpaces.s16, diff --git a/lib/features/intro/presentation/ui/widgets/intro_loading_widget.dart b/lib/features/intro/presentation/ui/widgets/intro_loading_widget.dart index de107f7..3d2667b 100644 --- a/lib/features/intro/presentation/ui/widgets/intro_loading_widget.dart +++ b/lib/features/intro/presentation/ui/widgets/intro_loading_widget.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:hadi_hoda_flutter/common_ui/resources/my_spaces.dart'; import 'package:hadi_hoda_flutter/common_ui/resources/my_text_style.dart'; +import 'package:hadi_hoda_flutter/features/intro/domain/entities/download_entity.dart'; class IntroLoadingWidget extends StatelessWidget { @@ -9,7 +10,7 @@ class IntroLoadingWidget extends StatelessWidget { this.loadingStream, }); - final Stream? loadingStream; + final Stream? loadingStream; @override Widget build(BuildContext context) { @@ -32,8 +33,8 @@ class IntroLoadingWidget extends StatelessWidget { ], ), ), - child: StreamBuilder( - initialData: 0, + child: StreamBuilder( + initialData: DownloadEntity(), stream: loadingStream, builder: (context, snapshot) { return Row( @@ -45,7 +46,7 @@ class IntroLoadingWidget extends StatelessWidget { child: AnimatedContainer( duration: const Duration(milliseconds: 300), padding: EdgeInsetsDirectional.only( - end: 260 - ((snapshot.data ?? 0) * 260 / 100), + end: 260 - ((snapshot.data?.percent ?? 0) * 260 / 100), ), decoration: BoxDecoration( color: Color(0xFF1F59BD).withValues(alpha: 0.25), @@ -71,7 +72,7 @@ class IntroLoadingWidget extends StatelessWidget { flex: 15, child: Center( child: Text( - '${snapshot.data?.toInt() ?? 0}%', + '${snapshot.data?.percent?.toInt() ?? 0}%', style: DinoKids.regular17.copyWith( color: Color(0XFF6E83A8), ), diff --git a/lib/features/language/data/datasource/language_datasource.dart b/lib/features/language/data/datasource/language_datasource.dart deleted file mode 100644 index 6c37a9d..0000000 --- a/lib/features/language/data/datasource/language_datasource.dart +++ /dev/null @@ -1,46 +0,0 @@ -import 'package:hadi_hoda_flutter/core/constants/my_api.dart'; -import 'package:hadi_hoda_flutter/core/constants/my_constants.dart'; -import 'package:hadi_hoda_flutter/core/network/http_request.dart'; -import 'package:hadi_hoda_flutter/core/params/language_params.dart'; -import 'package:hadi_hoda_flutter/core/response/base_response.dart'; -import 'package:hadi_hoda_flutter/core/utils/local_storage.dart'; -import 'package:hadi_hoda_flutter/features/level/data/model/level_model.dart'; -import 'package:hadi_hoda_flutter/features/level/domain/entity/level_entity.dart'; -import 'package:hadi_hoda_flutter/features/level/domain/entity/total_data_entity.dart'; -import 'package:hive/hive.dart'; - -abstract class ILanguageDatasource { - Future saveLevels({required LanguageParams params}); -} - -class LanguageDatasourceImpl implements ILanguageDatasource { - final IHttpRequest httpRequest; - - const LanguageDatasourceImpl(this.httpRequest); - - @override - Future saveLevels({required LanguageParams params}) async { - await LocalStorage.saveData( - key: MyConstants.selectLanguage, - value: params.code ?? 'fa', - ); - final Box data = Hive.box(MyConstants.levelBox); - final TotalDataEntity findData = data.values.singleWhere( - (e) => e.code == params.code, - orElse: () => TotalDataEntity(), - ); - - if (findData.code != params.code) { - final response = await httpRequest.get( - path: MyApi.levels, - header: params.toHeader, - ); - final List levels = BaseResponse.getDataList( - response?['result'], - (json) => LevelModel.fromJson(json), - ); - - await data.add(TotalDataEntity(code: params.code, levels: levels)); - } - } -} diff --git a/lib/features/language/data/repository_impl/language_repository_impl.dart b/lib/features/language/data/repository_impl/language_repository_impl.dart deleted file mode 100644 index 7441fac..0000000 --- a/lib/features/language/data/repository_impl/language_repository_impl.dart +++ /dev/null @@ -1,29 +0,0 @@ -import 'package:hadi_hoda_flutter/core/params/language_params.dart'; -import 'package:flutter/foundation.dart'; -import 'package:hadi_hoda_flutter/core/error_handler/my_exception.dart'; -import 'package:hadi_hoda_flutter/core/params/no_params.dart'; -import 'package:hadi_hoda_flutter/core/utils/data_state.dart'; -import 'package:hadi_hoda_flutter/features/language/data/datasource/language_datasource.dart'; -import 'package:hadi_hoda_flutter/features/language/domain/repository/language_repository.dart'; - -class LanguageRepositoryImpl implements ILanguageRepository { - final ILanguageDatasource datasource; - - const LanguageRepositoryImpl(this.datasource); - - @override - Future> saveLevels({required LanguageParams params}) async { - try { - await datasource.saveLevels(params: params); - return DataState.success(NoParams()); - } on MyException catch (e) { - return DataState.error(e); - } catch (e) { - if (kDebugMode) { - rethrow; - } else { - return DataState.error(MyException(errorMessage: '$e')); - } - } - } -} diff --git a/lib/features/language/domain/repository/language_repository.dart b/lib/features/language/domain/repository/language_repository.dart deleted file mode 100644 index 734c561..0000000 --- a/lib/features/language/domain/repository/language_repository.dart +++ /dev/null @@ -1,8 +0,0 @@ -import 'package:hadi_hoda_flutter/core/error_handler/my_exception.dart'; -import 'package:hadi_hoda_flutter/core/params/language_params.dart'; -import 'package:hadi_hoda_flutter/core/params/no_params.dart'; -import 'package:hadi_hoda_flutter/core/utils/data_state.dart'; - -abstract class ILanguageRepository { - Future> saveLevels({required LanguageParams params}); -} diff --git a/lib/features/language/domain/usecases/save_levels_usecase.dart b/lib/features/language/domain/usecases/save_levels_usecase.dart deleted file mode 100644 index 61c6546..0000000 --- a/lib/features/language/domain/usecases/save_levels_usecase.dart +++ /dev/null @@ -1,17 +0,0 @@ -import 'package:hadi_hoda_flutter/core/error_handler/my_exception.dart'; -import 'package:hadi_hoda_flutter/core/params/language_params.dart'; -import 'package:hadi_hoda_flutter/core/params/no_params.dart'; -import 'package:hadi_hoda_flutter/core/usecase/usecase.dart'; -import 'package:hadi_hoda_flutter/core/utils/data_state.dart'; -import 'package:hadi_hoda_flutter/features/language/domain/repository/language_repository.dart'; - -class SaveLevelsUseCase implements UseCase { - final ILanguageRepository repository; - - const SaveLevelsUseCase(this.repository); - - @override - Future> call(LanguageParams params) { - return repository.saveLevels(params: params); - } -} diff --git a/lib/features/language/presentation/bloc/language_bloc.dart b/lib/features/language/presentation/bloc/language_bloc.dart index c339a88..2dbf38f 100644 --- a/lib/features/language/presentation/bloc/language_bloc.dart +++ b/lib/features/language/presentation/bloc/language_bloc.dart @@ -1,26 +1,26 @@ import 'dart:async'; +import 'dart:io'; import 'package:bloc/bloc.dart'; import 'package:go_router/go_router.dart'; -import 'package:hadi_hoda_flutter/core/params/language_params.dart'; +import 'package:hadi_hoda_flutter/core/constants/my_constants.dart'; import 'package:hadi_hoda_flutter/core/routers/my_routes.dart'; -import 'package:hadi_hoda_flutter/core/status/base_status.dart'; import 'package:hadi_hoda_flutter/core/utils/context_provider.dart'; +import 'package:hadi_hoda_flutter/core/utils/local_storage.dart'; +import 'package:hadi_hoda_flutter/core/utils/storage_path.dart'; import 'package:hadi_hoda_flutter/features/language/domain/entity/language_entity.dart'; -import 'package:hadi_hoda_flutter/features/language/domain/usecases/save_levels_usecase.dart'; import 'package:hadi_hoda_flutter/features/language/presentation/bloc/language_event.dart'; import 'package:hadi_hoda_flutter/features/language/presentation/bloc/language_state.dart'; class LanguageBloc extends Bloc { /// ------------constructor------------ - LanguageBloc( - this._saveLevelsUseCase, - ) : super(const LanguageState()) { + LanguageBloc() : super(const LanguageState()) { + LocalStorage.saveData(key: MyConstants.firstLanguagePage, value: 'true'); on(_changeLanguageEvent); on(_saveLevelsEvent); + on(_initLanguageEvent); } /// ------------UseCases------------ - final SaveLevelsUseCase _saveLevelsUseCase; /// ------------Variables------------ final List languages = [ @@ -44,17 +44,31 @@ class LanguageBloc extends Bloc { SaveLevelsEvent event, Emitter emit, ) async { - emit(state.copyWith(saveLevelsStatus: const BaseLoading())); - await _saveLevelsUseCase(LanguageParams(code: state.selectedLang.code)).then( - (value) => value.fold( - (data) { - emit(state.copyWith(saveLevelsStatus: const BaseInit())); - ContextProvider.context!.goNamed(Routes.homePage); - }, - (error) { - emit(state.copyWith(saveLevelsStatus: const BaseInit())); - }, - ), - ); + await LocalStorage.saveData( + key: MyConstants.selectLanguage, + value: state.selectedLang.code ?? 'fa', + ); + if (Directory( + '${StoragePath.documentDir.path}/${state.selectedLang.code}/files') + .existsSync()) { + if (ContextProvider.context.mounted) { + ContextProvider.context.goNamed(Routes.homePage); + } + } else { + await Future.wait([ + LocalStorage.deleteData(key: MyConstants.downloadCompleted), + LocalStorage.deleteData(key: MyConstants.extractCompleted), + ]); + if (ContextProvider.context.mounted) { + ContextProvider.context.goNamed(Routes.introPage); + } + } + } + + FutureOr _initLanguageEvent(InitLanguageEvent event, Emitter emit) { + final String selectedLanguage = LocalStorage.readData(key: MyConstants.selectLanguage).isEmpty + ? 'fa' + : LocalStorage.readData(key: MyConstants.selectLanguage); + emit(state.copyWith(selectedLang: LanguageEntity(code: selectedLanguage))); } } diff --git a/lib/features/language/presentation/bloc/language_event.dart b/lib/features/language/presentation/bloc/language_event.dart index 2531db4..accf591 100644 --- a/lib/features/language/presentation/bloc/language_event.dart +++ b/lib/features/language/presentation/bloc/language_event.dart @@ -3,14 +3,15 @@ import 'package:hadi_hoda_flutter/features/language/domain/entity/language_entit sealed class LanguageEvent { const LanguageEvent(); } - class ChangeLanguageEvent extends LanguageEvent { final LanguageEntity lang; const ChangeLanguageEvent(this.lang); } - class SaveLevelsEvent extends LanguageEvent { const SaveLevelsEvent(); } +class InitLanguageEvent extends LanguageEvent { + const InitLanguageEvent(); +} diff --git a/lib/features/language/presentation/ui/language_page.dart b/lib/features/language/presentation/ui/language_page.dart index 4c81130..cd5af65 100644 --- a/lib/features/language/presentation/ui/language_page.dart +++ b/lib/features/language/presentation/ui/language_page.dart @@ -1,11 +1,9 @@ -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:hadi_hoda_flutter/common_ui/resources/my_assets.dart'; +import 'package:hadi_hoda_flutter/common_ui/resources/my_colors.dart'; import 'package:hadi_hoda_flutter/common_ui/resources/my_spaces.dart'; import 'package:hadi_hoda_flutter/common_ui/resources/my_text_style.dart'; -import 'package:hadi_hoda_flutter/common_ui/theme/my_theme.dart'; -import 'package:hadi_hoda_flutter/core/status/base_status.dart'; import 'package:hadi_hoda_flutter/core/utils/my_image.dart'; import 'package:hadi_hoda_flutter/core/utils/my_localization.dart'; import 'package:hadi_hoda_flutter/core/utils/screen_size.dart'; @@ -71,7 +69,7 @@ class LanguagePage extends StatelessWidget { Expanded _list(BuildContext context) { return Expanded( child: Material( - color: context.noColor, + color: MyColors.transparent, child: Column( mainAxisAlignment: MainAxisAlignment.center, children: List.generate( @@ -90,7 +88,7 @@ class LanguagePage extends StatelessWidget { }, title: Text(context.read().languages[index].title ?? ''), titleTextStyle: Marhey.medium16.copyWith( - color: context.primaryColor, + color: MyColors.white, ), contentPadding: EdgeInsets.symmetric( vertical: MySpaces.s12, @@ -100,18 +98,6 @@ class LanguagePage extends StatelessWidget { minTileHeight: 0, minLeadingWidth: 0, horizontalTitleGap: MySpaces.s12, - trailing: BlocBuilder( - builder: (context, state) { - if (state.saveLevelsStatus is BaseLoading && (state - .selectedLang.code == languageBloc.languages[index].code)) { - return CupertinoActivityIndicator( - color: context.primaryColor, - ); - } else { - return SizedBox.shrink(); - } - }, - ), leading: state.selectedLang.code == languageBloc.languages[index].code ? Container( height: 17, @@ -137,8 +123,8 @@ class LanguagePage extends StatelessWidget { shape: RoundedRectangleBorder( borderRadius: BorderRadius.all(Radius.circular(12)), ), - selectedTileColor: context.primaryColor.withValues(alpha: 0.2), - selectedColor: context.primaryColor, + selectedTileColor: MyColors.white.withValues(alpha: 0.2), + selectedColor: MyColors.white, ); } ), diff --git a/lib/features/level/presentation/ui/widgets/level_widget.dart b/lib/features/level/presentation/ui/widgets/level_widget.dart index ce1e44c..420c6c4 100644 --- a/lib/features/level/presentation/ui/widgets/level_widget.dart +++ b/lib/features/level/presentation/ui/widgets/level_widget.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:hadi_hoda_flutter/common_ui/resources/my_assets.dart'; +import 'package:hadi_hoda_flutter/common_ui/resources/my_colors.dart'; import 'package:hadi_hoda_flutter/common_ui/resources/my_text_style.dart'; -import 'package:hadi_hoda_flutter/common_ui/theme/my_theme.dart'; import 'package:hadi_hoda_flutter/core/utils/my_image.dart'; import 'package:hadi_hoda_flutter/features/level/domain/entity/level_entity.dart'; @@ -43,7 +43,7 @@ class LevelWidget extends StatelessWidget { Text( '$index', style: DinoKids.regular26.copyWith( - color: context.primaryColor, + color: MyColors.white, shadows: [ Shadow( color: Color(0XFF5B5B5B), diff --git a/lib/features/question/presentation/ui/question_page.dart b/lib/features/question/presentation/ui/question_page.dart index 9e68191..9663bf0 100644 --- a/lib/features/question/presentation/ui/question_page.dart +++ b/lib/features/question/presentation/ui/question_page.dart @@ -1,9 +1,9 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:hadi_hoda_flutter/common_ui/resources/my_assets.dart'; +import 'package:hadi_hoda_flutter/common_ui/resources/my_colors.dart'; import 'package:hadi_hoda_flutter/common_ui/resources/my_spaces.dart'; import 'package:hadi_hoda_flutter/common_ui/resources/my_text_style.dart'; -import 'package:hadi_hoda_flutter/common_ui/theme/my_theme.dart'; import 'package:hadi_hoda_flutter/core/utils/gap.dart'; import 'package:hadi_hoda_flutter/core/utils/my_image.dart'; import 'package:hadi_hoda_flutter/core/utils/my_localization.dart'; @@ -82,7 +82,7 @@ class QuestionPage extends StatelessWidget { builder: (context, state) => Text( state.levelEntity?.title ?? '', style: Marhey.bold14.copyWith( - color: context.primaryColor, + color: MyColors.white, ), ), ), @@ -109,7 +109,7 @@ class QuestionPage extends StatelessWidget { builder: (context, state) => Text( 'Question ${state.currentStep} / ${state.levelEntity?.questions?.length ?? 0}', style: Marhey.medium12.copyWith( - color: context.primaryColor.withValues(alpha: 0.5), + color: MyColors.white.withValues(alpha: 0.5), shadows: [ Shadow( offset: Offset(0, 1), @@ -125,7 +125,7 @@ class QuestionPage extends StatelessWidget { state.levelEntity?.questions?[state.currentStep].title ?? '', textAlign: TextAlign.center, style: Marhey.medium12.copyWith( - color: context.primaryColor, + color: MyColors.white, shadows: [ Shadow( offset: Offset(0, 1), diff --git a/lib/features/question/presentation/ui/widgets/refresh_button.dart b/lib/features/question/presentation/ui/widgets/refresh_button.dart index 801678e..2f4a8bf 100644 --- a/lib/features/question/presentation/ui/widgets/refresh_button.dart +++ b/lib/features/question/presentation/ui/widgets/refresh_button.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:hadi_hoda_flutter/common_ui/theme/my_theme.dart'; +import 'package:hadi_hoda_flutter/common_ui/resources/my_colors.dart'; class RefreshButton extends StatelessWidget { const RefreshButton({super.key, this.onTap,}); @@ -9,7 +9,7 @@ class RefreshButton extends StatelessWidget { @override Widget build(BuildContext context) { return Material( - color: context.noColor, + color: MyColors.transparent, child: Ink( height: 48, width: 48, diff --git a/lib/init_bindings.dart b/lib/init_bindings.dart index bad6e5e..997baae 100644 --- a/lib/init_bindings.dart +++ b/lib/init_bindings.dart @@ -12,10 +12,7 @@ import 'package:hadi_hoda_flutter/features/intro/data/repository_impl/intro_repo import 'package:hadi_hoda_flutter/features/intro/domain/repository/intro_repository.dart'; import 'package:hadi_hoda_flutter/features/intro/domain/usecases/get_files_usecase.dart'; import 'package:hadi_hoda_flutter/features/intro/domain/usecases/loading_stream_usecase.dart'; -import 'package:hadi_hoda_flutter/features/language/data/datasource/language_datasource.dart'; -import 'package:hadi_hoda_flutter/features/language/data/repository_impl/language_repository_impl.dart'; -import 'package:hadi_hoda_flutter/features/language/domain/repository/language_repository.dart'; -import 'package:hadi_hoda_flutter/features/language/domain/usecases/save_levels_usecase.dart'; +import 'package:hadi_hoda_flutter/features/intro/domain/usecases/save_levels_usecase.dart'; import 'package:hadi_hoda_flutter/features/level/data/datasource/level_datasource.dart'; import 'package:hadi_hoda_flutter/features/level/data/repository_impl/level_repository_impl.dart'; import 'package:hadi_hoda_flutter/features/level/domain/entity/level_entity.dart'; @@ -52,12 +49,10 @@ void initBindings() { locator.registerLazySingleton(() => IntroDatasourceImpl(locator())); locator.registerLazySingleton(() => IntroRepositoryImpl(locator())); locator.registerLazySingleton(() => GetFilesUseCase(locator())); + locator.registerLazySingleton(() => SaveLevelsUseCase(locator())); locator.registerLazySingleton(() => LoadingStreamUseCase(locator())); /// Language Feature - locator.registerLazySingleton(() => LanguageDatasourceImpl(locator())); - locator.registerLazySingleton(() => LanguageRepositoryImpl(locator())); - locator.registerLazySingleton(() => SaveLevelsUseCase(locator())); /// Home Feature locator.registerLazySingleton(() => HomeDatasourceImpl(locator())); diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index fd36a8d..66f926e 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -3,5 +3,10 @@ "about_us_desc" : "Rive combines an interactive design tool, a new stateful graphics format, a lightweight multi-platform runtime, and a blazing-fast vector renderer. \nThis end-to-end pipeline brings interfaces to life with motion. It gives designers and devs the tools to build.", "tap_to_select": "Tap the correct option to select.", "select_language": "Select language", - "select": "Select" + "select": "Select", + "please_wait": "Please wait a few moments...", + "downloading_data": "Downloading initial data", + "lost_connection": "Lost connection!", + "try_again": "Try Again", + "connected_to_internet": "You must be connected to the internet to download the initial game data." } \ No newline at end of file diff --git a/lib/l10n/app_localizations.dart b/lib/l10n/app_localizations.dart index 8b63165..7d3e5a1 100644 --- a/lib/l10n/app_localizations.dart +++ b/lib/l10n/app_localizations.dart @@ -123,6 +123,36 @@ abstract class AppLocalizations { /// In en, this message translates to: /// **'Select'** String get select; + + /// No description provided for @please_wait. + /// + /// In en, this message translates to: + /// **'Please wait a few moments...'** + String get please_wait; + + /// No description provided for @downloading_data. + /// + /// In en, this message translates to: + /// **'Downloading initial data'** + String get downloading_data; + + /// No description provided for @lost_connection. + /// + /// In en, this message translates to: + /// **'Lost connection!'** + String get lost_connection; + + /// No description provided for @try_again. + /// + /// In en, this message translates to: + /// **'Try Again'** + String get try_again; + + /// No description provided for @connected_to_internet. + /// + /// In en, this message translates to: + /// **'You must be connected to the internet to download the initial game data.'** + String get connected_to_internet; } class _AppLocalizationsDelegate diff --git a/lib/l10n/app_localizations_en.dart b/lib/l10n/app_localizations_en.dart index 290f727..521588d 100644 --- a/lib/l10n/app_localizations_en.dart +++ b/lib/l10n/app_localizations_en.dart @@ -23,4 +23,20 @@ class AppLocalizationsEn extends AppLocalizations { @override String get select => 'Select'; + + @override + String get please_wait => 'Please wait a few moments...'; + + @override + String get downloading_data => 'Downloading initial data'; + + @override + String get lost_connection => 'Lost connection!'; + + @override + String get try_again => 'Try Again'; + + @override + String get connected_to_internet => + 'You must be connected to the internet to download the initial game data.'; }