diff --git a/assets/videos/intro_1.mp4 b/assets/videos/intro_1.mp4 new file mode 100644 index 0000000..d4e82b4 Binary files /dev/null and b/assets/videos/intro_1.mp4 differ diff --git a/assets/videos/intro_2.mp4 b/assets/videos/intro_2.mp4 new file mode 100644 index 0000000..37676a5 Binary files /dev/null and b/assets/videos/intro_2.mp4 differ diff --git a/assets/videos/intro_3.mp4 b/assets/videos/intro_3.mp4 new file mode 100644 index 0000000..56f10d9 Binary files /dev/null and b/assets/videos/intro_3.mp4 differ diff --git a/assets/videos/intro_4.mp4 b/assets/videos/intro_4.mp4 new file mode 100644 index 0000000..1b7df80 Binary files /dev/null and b/assets/videos/intro_4.mp4 differ diff --git a/assets/videos/intro_5.mp4 b/assets/videos/intro_5.mp4 new file mode 100644 index 0000000..c456f63 Binary files /dev/null and b/assets/videos/intro_5.mp4 differ diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist index 4d55364..3291dc0 100644 --- a/ios/Runner/Info.plist +++ b/ios/Runner/Info.plist @@ -2,6 +2,11 @@ + NSAppTransportSecurity + + NSAllowsArbitraryLoads + + CFBundleDevelopmentRegion $(DEVELOPMENT_LANGUAGE) CFBundleDisplayName diff --git a/lib/core/utils/pre_cache_image.dart b/lib/core/utils/pre_cache_image.dart new file mode 100644 index 0000000..3651b51 --- /dev/null +++ b/lib/core/utils/pre_cache_image.dart @@ -0,0 +1,11 @@ +import 'package:flutter/material.dart'; +import 'package:hadi_hoda_flutter/common_ui/resources/my_assets.dart'; +import 'package:hadi_hoda_flutter/core/utils/my_context.dart'; + +Future preCacheImages() async { + await Future.wait( + MyAssets.images.map( + (assetPath) => precacheImage(AssetImage(assetPath), MyContext.get), + ), + ); +} diff --git a/lib/core/widgets/answer_box/styles/picture_box.dart b/lib/core/widgets/answer_box/styles/picture_box.dart index b5d34f5..6566b12 100644 --- a/lib/core/widgets/answer_box/styles/picture_box.dart +++ b/lib/core/widgets/answer_box/styles/picture_box.dart @@ -19,6 +19,7 @@ class AnswerPictureBox extends StatelessWidget { required this.correctAnswer, this.onTap, this.autostart = Autostart.no, + this.showIndex = true, }); final bool selected; @@ -27,6 +28,7 @@ class AnswerPictureBox extends StatelessWidget { final int correctAnswer; final VoidCallback? onTap; final Autostart autostart; + final bool showIndex; @override Widget build(BuildContext context) { @@ -72,25 +74,26 @@ class AnswerPictureBox extends StatelessWidget { ), ), ), - PositionedDirectional( - top: 0, - child: Container( - width: MySpaces.s34, - alignment: Alignment.center, - decoration: BoxDecoration( - color: Color(0XFFF2F7FF), - borderRadius: BorderRadius.vertical( - bottom: Radius.circular(10), + if (showIndex) + PositionedDirectional( + top: 0, + child: Container( + width: MySpaces.s34, + alignment: Alignment.center, + decoration: BoxDecoration( + color: Color(0XFFF2F7FF), + borderRadius: BorderRadius.vertical( + bottom: Radius.circular(10), + ), ), - ), - child: Text( - '$index', - style: MYTextStyle.titr1.copyWith( - color: Color(0XFF9B85D8), + child: Text( + '$index', + style: MYTextStyle.titr1.copyWith( + color: Color(0XFF9B85D8), + ), ), ), ), - ), if(selected) PositionedDirectional( top: setSize(context: context, mobile: MySpaces.s8, tablet: MySpaces.s20), diff --git a/lib/features/download/data/datasource/download_datasource.dart b/lib/features/download/data/datasource/download_datasource.dart index 843d969..1b452fb 100644 --- a/lib/features/download/data/datasource/download_datasource.dart +++ b/lib/features/download/data/datasource/download_datasource.dart @@ -90,11 +90,11 @@ class DownloadDatasourceImpl implements IDownloadDatasource { 'lang': selectedLanguage, }, onReceive: (count, total) { - streamController.add(DownloadEntity( - count: count / 1, - total: total / 1, - percent: (count / total) * 100, - )); + // streamController.add(DownloadEntity( + // count: count / 1, + // total: total / 1, + // percent: (count / total) * 100, + // )); }, ).then((value) async { await LocalStorage.saveData( diff --git a/lib/features/download/presentation/bloc/download_bloc.dart b/lib/features/download/presentation/bloc/download_bloc.dart index 4c94b16..ffe9310 100644 --- a/lib/features/download/presentation/bloc/download_bloc.dart +++ b/lib/features/download/presentation/bloc/download_bloc.dart @@ -8,6 +8,7 @@ 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/local_storage.dart'; import 'package:hadi_hoda_flutter/core/utils/my_context.dart'; +import 'package:hadi_hoda_flutter/core/utils/pre_cache_image.dart'; import 'package:hadi_hoda_flutter/features/download/domain/entities/download_entity.dart'; import 'package:hadi_hoda_flutter/features/download/domain/usecases/get_audios_usecase.dart'; import 'package:hadi_hoda_flutter/features/download/domain/usecases/get_images_usecase.dart'; @@ -25,6 +26,7 @@ class DownloadBloc extends Bloc { this._saveLevelsUseCase, ) : super(const DownloadState()) { + preCacheImages(); on(_getImagesEvent); on(_getAudiosEvent); on(_saveLevelsEvent); diff --git a/lib/features/intro/presentation/bloc/intro_bloc.dart b/lib/features/intro/presentation/bloc/intro_bloc.dart index dbc5205..b863df4 100644 --- a/lib/features/intro/presentation/bloc/intro_bloc.dart +++ b/lib/features/intro/presentation/bloc/intro_bloc.dart @@ -14,11 +14,24 @@ import 'package:hadi_hoda_flutter/features/intro/presentation/ui/screens/intro_2 import 'package:hadi_hoda_flutter/features/intro/presentation/ui/screens/intro_3_screen.dart'; import 'package:hadi_hoda_flutter/features/intro/presentation/ui/screens/intro_4_screen.dart'; import 'package:hadi_hoda_flutter/features/intro/presentation/ui/screens/intro_5_screen.dart'; +import 'package:pod_player/pod_player.dart'; class IntroBloc extends Bloc { /// ------------constructor------------ - IntroBloc() : super(const IntroState()){ - on(_changeIntroEvent); + IntroBloc() : super(const IntroState()) { + initVideos(); + on(_initVideosEvent); + on(_changeVideosEvent); + } + + @override + Future close() { + podController1.dispose(); + podController2.dispose(); + podController3.dispose(); + podController4.dispose(); + podController5.dispose(); + return super.close(); } /// ------------UseCases------------ @@ -33,6 +46,21 @@ class IntroBloc extends Bloc { ]; /// ------------Controllers------------ + final PodPlayerController podController1 = PodPlayerController( + playVideoFrom: PlayVideoFrom.asset('assets/videos/intro_1.mp4'), + ); + final PodPlayerController podController2 = PodPlayerController( + playVideoFrom: PlayVideoFrom.asset('assets/videos/intro_2.mp4'), + ); + final PodPlayerController podController3 = PodPlayerController( + playVideoFrom: PlayVideoFrom.asset('assets/videos/intro_3.mp4'), + ); + final PodPlayerController podController4 = PodPlayerController( + playVideoFrom: PlayVideoFrom.asset('assets/videos/intro_4.mp4'), + ); + final PodPlayerController podController5 = PodPlayerController( + playVideoFrom: PlayVideoFrom.asset('assets/videos/intro_5.mp4'), + ); /// ------------Functions------------ Future goToHomePage() async { @@ -43,11 +71,46 @@ class IntroBloc extends Bloc { } /// ------------Api Calls------------ - FutureOr _changeIntroEvent(ChangeIntroEvent event, Emitter emit) async { - if (state.currentIntro < intros.length - 1) { - emit(state.copyWith(currentIntro: state.currentIntro + 1)); - } else { - goToHomePage(); + FutureOr _changeVideosEvent(ChangeVideosEvent event, Emitter emit) async { + switch (state.currentIntro) { + case 0: + podController2.play(); + emit(state.copyWith(currentIntro: 1)); + break; + case 1: + podController3.play(); + emit(state.copyWith(currentIntro: 2)); + break; + case 2: + podController4.play(); + emit(state.copyWith(currentIntro: 3)); + break; + case 3: + podController5.play(); + emit(state.copyWith(currentIntro: 4)); + break; + case 4: + goToHomePage(); + break; } } + + Future initVideos() async { + await Future.wait([ + podController1.initialise(), + podController2.initialise(), + podController3.initialise(), + podController4.initialise(), + podController5.initialise(), + ]); + podController1.play(); + add(InitVideosEvent()); + } + + FutureOr _initVideosEvent( + InitVideosEvent event, + Emitter emit, + ) async { + emit(state.copyWith(currentIntro: 0)); + } } diff --git a/lib/features/intro/presentation/bloc/intro_event.dart b/lib/features/intro/presentation/bloc/intro_event.dart index 5a38075..5577c28 100644 --- a/lib/features/intro/presentation/bloc/intro_event.dart +++ b/lib/features/intro/presentation/bloc/intro_event.dart @@ -2,4 +2,6 @@ sealed class IntroEvent { const IntroEvent(); } -class ChangeIntroEvent extends IntroEvent {} +class InitVideosEvent extends IntroEvent {} + +class ChangeVideosEvent extends IntroEvent {} diff --git a/lib/features/intro/presentation/ui/intro_page.dart b/lib/features/intro/presentation/ui/intro_page.dart index 87aa98e..0ef36e9 100644 --- a/lib/features/intro/presentation/ui/intro_page.dart +++ b/lib/features/intro/presentation/ui/intro_page.dart @@ -16,7 +16,7 @@ class IntroPage extends StatelessWidget { return Scaffold( body: SizedBox.expand( child: GestureDetector( - onTap: () => context.read().add(ChangeIntroEvent()), + onTap: () => context.read().add(ChangeVideosEvent()), child: Stack( children: [ _mainScreen(), diff --git a/lib/features/intro/presentation/ui/screens/intro_1_screen.dart b/lib/features/intro/presentation/ui/screens/intro_1_screen.dart index 7e76806..37926cd 100644 --- a/lib/features/intro/presentation/ui/screens/intro_1_screen.dart +++ b/lib/features/intro/presentation/ui/screens/intro_1_screen.dart @@ -1,54 +1,24 @@ 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_spaces.dart'; -import 'package:hadi_hoda_flutter/core/utils/my_localization.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:hadi_hoda_flutter/core/utils/screen_size.dart'; -import 'package:hadi_hoda_flutter/core/utils/set_platform_size.dart'; -import 'package:hadi_hoda_flutter/core/widgets/animations/slide_up_fade.dart'; -import 'package:hadi_hoda_flutter/core/widgets/images/my_image.dart'; -import 'package:hadi_hoda_flutter/features/intro/presentation/ui/widgets/bubble_chat_widget.dart'; +import 'package:hadi_hoda_flutter/features/intro/presentation/bloc/intro_bloc.dart'; +import 'package:pod_player/pod_player.dart'; class Intro1Screen extends StatelessWidget { const Intro1Screen({super.key}); @override Widget build(BuildContext context) { - return Stack( - alignment: Alignment.center, - children: [ - Positioned.fill( - child: MyImage(image: MyAssets.intro_1, fit: BoxFit.cover), - ), - PositionedDirectional( - end: setSize( - context: context, - mobile: MySpaces.s10, - tablet: 0.15.w, - ), - top: setSize( - context: context, - mobile: 0.15.h, - tablet: 0.25.h, - ), - width: 290, - child: SlideUpFade( - delay: Duration(milliseconds: 300), - child: BubbleChatWidget( - text: context.translate.intro_1_1, - flip: true, - ), - ), - ), - PositionedDirectional( - start: setSize(context: context, mobile: MySpaces.s30, tablet: 0.2.w), - top: setSize(context: context, mobile: 0.3.h, tablet: 0.35.h), - width: 250, - child: SlideUpFade( - delay: Duration(milliseconds: 800), - child: BubbleChatWidget(text: context.translate.intro_1_2), - ), - ), - ], + return SizedBox.expand( + child: PodVideoPlayer( + controller: context.read().podController1, + overlayBuilder: (options) => SizedBox.shrink(), + alwaysShowProgressBar: false, + videoAspectRatio: context.widthScreen / context.heightScreen, + frameAspectRatio: context.widthScreen / context.heightScreen, + backgroundColor: Color(0XFF00154C), + onLoading: (context) => SizedBox.shrink(), + ), ); } } diff --git a/lib/features/intro/presentation/ui/screens/intro_2_screen.dart b/lib/features/intro/presentation/ui/screens/intro_2_screen.dart index 47ed928..6ecdacb 100644 --- a/lib/features/intro/presentation/ui/screens/intro_2_screen.dart +++ b/lib/features/intro/presentation/ui/screens/intro_2_screen.dart @@ -1,37 +1,25 @@ 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_spaces.dart'; -import 'package:hadi_hoda_flutter/core/utils/my_localization.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:hadi_hoda_flutter/common_ui/resources/my_colors.dart'; import 'package:hadi_hoda_flutter/core/utils/screen_size.dart'; -import 'package:hadi_hoda_flutter/core/utils/set_platform_size.dart'; -import 'package:hadi_hoda_flutter/core/widgets/animations/slide_up_fade.dart'; -import 'package:hadi_hoda_flutter/core/widgets/images/my_image.dart'; -import 'package:hadi_hoda_flutter/features/intro/presentation/ui/widgets/bubble_chat_widget.dart'; +import 'package:hadi_hoda_flutter/features/intro/presentation/bloc/intro_bloc.dart'; +import 'package:pod_player/pod_player.dart'; class Intro2Screen extends StatelessWidget { const Intro2Screen({super.key}); @override Widget build(BuildContext context) { - return Stack( - alignment: Alignment.center, - children: [ - Positioned.fill( - child: Transform.flip( - flipX: true, - child: MyImage(image: MyAssets.intro_2, fit: BoxFit.cover), - ), - ), - PositionedDirectional( - end: setSize(context: context, mobile: MySpaces.s40, tablet: 0.3.w), - top: setSize(context: context, mobile: 0.17.h, tablet: 0.23.h), - width: 250, - child: SlideUpFade( - delay: Duration(milliseconds: 300), - child: BubbleChatWidget(text: context.translate.intro_2), - ), - ), - ], + return SizedBox.expand( + child: PodVideoPlayer( + controller: context.read().podController2, + overlayBuilder: (options) => SizedBox.shrink(), + alwaysShowProgressBar: false, + videoAspectRatio: context.widthScreen / context.heightScreen, + frameAspectRatio: context.widthScreen / context.heightScreen, + backgroundColor: MyColors.transparent, + onLoading: (context) => SizedBox.shrink(), + ), ); } } diff --git a/lib/features/intro/presentation/ui/screens/intro_3_screen.dart b/lib/features/intro/presentation/ui/screens/intro_3_screen.dart index 3386651..1330dff 100644 --- a/lib/features/intro/presentation/ui/screens/intro_3_screen.dart +++ b/lib/features/intro/presentation/ui/screens/intro_3_screen.dart @@ -1,37 +1,25 @@ 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_spaces.dart'; -import 'package:hadi_hoda_flutter/core/utils/my_localization.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:hadi_hoda_flutter/common_ui/resources/my_colors.dart'; import 'package:hadi_hoda_flutter/core/utils/screen_size.dart'; -import 'package:hadi_hoda_flutter/core/utils/set_platform_size.dart'; -import 'package:hadi_hoda_flutter/core/widgets/animations/slide_up_fade.dart'; -import 'package:hadi_hoda_flutter/core/widgets/images/my_image.dart'; -import 'package:hadi_hoda_flutter/features/intro/presentation/ui/widgets/bubble_chat_widget.dart'; +import 'package:hadi_hoda_flutter/features/intro/presentation/bloc/intro_bloc.dart'; +import 'package:pod_player/pod_player.dart'; class Intro3Screen extends StatelessWidget { const Intro3Screen({super.key}); @override Widget build(BuildContext context) { - return Stack( - alignment: Alignment.center, - children: [ - Positioned.fill( - child: MyImage(image: MyAssets.intro_3, fit: BoxFit.cover), - ), - PositionedDirectional( - start: setSize(context: context, mobile: MySpaces.s30), - top: setSize(context: context, mobile: 180, tablet: 0.25.h), - width: 270, - child: SlideUpFade( - delay: Duration(milliseconds: 300), - child: BubbleChatWidget( - text: context.translate.intro_3, - flip: true, - ), - ), - ), - ], + return SizedBox.expand( + child: PodVideoPlayer( + controller: context.read().podController3, + overlayBuilder: (options) => SizedBox.shrink(), + alwaysShowProgressBar: false, + videoAspectRatio: context.widthScreen / context.heightScreen, + frameAspectRatio: context.widthScreen / context.heightScreen, + backgroundColor: MyColors.transparent, + onLoading: (context) => SizedBox.shrink(), + ), ); } } diff --git a/lib/features/intro/presentation/ui/screens/intro_4_screen.dart b/lib/features/intro/presentation/ui/screens/intro_4_screen.dart index e7a1562..b365751 100644 --- a/lib/features/intro/presentation/ui/screens/intro_4_screen.dart +++ b/lib/features/intro/presentation/ui/screens/intro_4_screen.dart @@ -1,36 +1,25 @@ 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_spaces.dart'; -import 'package:hadi_hoda_flutter/core/utils/my_localization.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:hadi_hoda_flutter/common_ui/resources/my_colors.dart'; import 'package:hadi_hoda_flutter/core/utils/screen_size.dart'; -import 'package:hadi_hoda_flutter/core/utils/set_platform_size.dart'; -import 'package:hadi_hoda_flutter/core/widgets/animations/slide_up_fade.dart'; -import 'package:hadi_hoda_flutter/core/widgets/images/my_image.dart'; -import 'package:hadi_hoda_flutter/features/intro/presentation/ui/widgets/bubble_chat_widget.dart'; +import 'package:hadi_hoda_flutter/features/intro/presentation/bloc/intro_bloc.dart'; +import 'package:pod_player/pod_player.dart'; class Intro4Screen extends StatelessWidget { const Intro4Screen({super.key}); @override Widget build(BuildContext context) { - return Stack( - alignment: Alignment.center, - children: [ - Positioned.fill( - child: MyImage(image: MyAssets.intro_4, fit: BoxFit.cover), - ), - PositionedDirectional( - start: setSize(context: context, mobile: MySpaces.s10, tablet: 0.2.w), - bottom: setSize(context: context, mobile: 0.4.h, tablet: 0.4.h), - width: 237, - child: SlideUpFade( - delay: Duration(milliseconds: 300), - child: BubbleChatWidget( - text: context.translate.intro_4, - ), - ), - ), - ], + return SizedBox.expand( + child: PodVideoPlayer( + controller: context.read().podController4, + overlayBuilder: (options) => SizedBox.shrink(), + alwaysShowProgressBar: false, + videoAspectRatio: context.widthScreen / context.heightScreen, + frameAspectRatio: context.widthScreen / context.heightScreen, + backgroundColor: MyColors.transparent, + onLoading: (context) => SizedBox.shrink(), + ), ); } } diff --git a/lib/features/intro/presentation/ui/screens/intro_5_screen.dart b/lib/features/intro/presentation/ui/screens/intro_5_screen.dart index 7228d8f..7a235cf 100644 --- a/lib/features/intro/presentation/ui/screens/intro_5_screen.dart +++ b/lib/features/intro/presentation/ui/screens/intro_5_screen.dart @@ -1,34 +1,25 @@ import 'package:flutter/material.dart'; -import 'package:hadi_hoda_flutter/common_ui/resources/my_assets.dart'; -import 'package:hadi_hoda_flutter/core/utils/my_localization.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:hadi_hoda_flutter/common_ui/resources/my_colors.dart'; import 'package:hadi_hoda_flutter/core/utils/screen_size.dart'; -import 'package:hadi_hoda_flutter/core/utils/set_platform_size.dart'; -import 'package:hadi_hoda_flutter/core/widgets/animations/slide_up_fade.dart'; -import 'package:hadi_hoda_flutter/core/widgets/images/my_image.dart'; -import 'package:hadi_hoda_flutter/features/intro/presentation/ui/widgets/bubble_chat_widget.dart'; +import 'package:hadi_hoda_flutter/features/intro/presentation/bloc/intro_bloc.dart'; +import 'package:pod_player/pod_player.dart'; class Intro5Screen extends StatelessWidget { const Intro5Screen({super.key}); @override Widget build(BuildContext context) { - return Stack( - alignment: Alignment.center, - children: [ - Positioned.fill( - child: MyImage(image: MyAssets.intro_5, fit: BoxFit.cover), - ), - PositionedDirectional( - top: setSize(context: context, mobile: 0.37.h, tablet: 0.42.h), - width: 200, - child: SlideUpFade( - delay: Duration(milliseconds: 300), - child: BubbleChatWidget( - text: context.translate.intro_5, - ), - ), - ), - ], + return SizedBox.expand( + child: PodVideoPlayer( + controller: context.read().podController5, + overlayBuilder: (options) => SizedBox.shrink(), + alwaysShowProgressBar: false, + videoAspectRatio: context.widthScreen / context.heightScreen, + frameAspectRatio: context.widthScreen / context.heightScreen, + backgroundColor: MyColors.transparent, + onLoading: (context) => SizedBox.shrink(), + ), ); } } diff --git a/lib/features/question/presentation/bloc/question_bloc.dart b/lib/features/question/presentation/bloc/question_bloc.dart index 4fe07d3..08873ad 100644 --- a/lib/features/question/presentation/bloc/question_bloc.dart +++ b/lib/features/question/presentation/bloc/question_bloc.dart @@ -45,7 +45,6 @@ class QuestionBloc extends Bloc { _backgroundAudioService.dispose(); answerAnimationController.dispose(); imageAnimationController.dispose(); - titleController.dispose(); return super.close(); } @@ -77,16 +76,20 @@ class QuestionBloc extends Bloc { final AudioService _effectAudioService; late final AnimationController answerAnimationController; late final AnimationController imageAnimationController; - final ScrollController titleController = ScrollController(); /// ------------Functions------------ - void startScrollTitle({Duration? audioDuration}) { - if (audioDuration == null || audioDuration == Duration.zero) return; - titleController.animateTo( - titleController.position.maxScrollExtent, - duration: audioDuration, - curve: Curves.linear - ); + // void startScrollTitle({Duration? audioDuration}) { + // if (audioDuration == null || audioDuration == Duration.zero) return; + // titleController.animateTo( + // titleController.position.maxScrollExtent, + // duration: audioDuration, + // curve: Curves.linear + // ); + // } + + Future showImageWithDelayed() async { + await Future.delayed(const Duration(milliseconds: 500)); + imageAnimationController.forward(); } void showHadith({required BuildContext context}) { @@ -136,11 +139,7 @@ class QuestionBloc extends Bloc { } Future playQuestionAudio() async { - if(titleController.hasClients){ - titleController.jumpTo(0); - } - Duration? duration = await _mainAudioService.setAudio(filePath: state.currentQuestion?.audio); - startScrollTitle(audioDuration: duration); + await _mainAudioService.setAudio(filePath: state.currentQuestion?.audio); await _mainAudioService.play(); } @@ -262,7 +261,6 @@ class QuestionBloc extends Bloc { emit(state.copyWith(correctAnswer: event.chooseCorrectAnswer)); if (event.chooseCorrectAnswer) { - answerAnimationController.reverse(); await showAnswerDialog( context: MyContext.get, correctAudio: state.currentQuestion?.correctAudio, @@ -292,6 +290,7 @@ class QuestionBloc extends Bloc { } } else { showingAnswerSequence(show: true); + answerAnimationController.reverse(); imageAnimationController.forward(); await playQuestionAudio(); imageAnimationController.reverse(); diff --git a/lib/features/question/presentation/ui/screens/question_screen.dart b/lib/features/question/presentation/ui/screens/question_screen.dart index d0d1afb..ba2f40b 100644 --- a/lib/features/question/presentation/ui/screens/question_screen.dart +++ b/lib/features/question/presentation/ui/screens/question_screen.dart @@ -76,8 +76,6 @@ class _QuestionScreenState extends State with TickerProviderStat return Column( children: [ _stepper(), - _titles(context), - MySpaces.s20.gapHeight, Expanded( child: Stack( children: [ @@ -95,11 +93,13 @@ class _QuestionScreenState extends State with TickerProviderStat return Column( children: [ Spacer(), - FadeAnimController( - controller: context.read().imageAnimationController, - child: BlocBuilder( - builder: (context, state) => AnswerPictureBox( + BlocBuilder( + builder: (context, state) => FadeAnimController( + key: Key('${state.currentQuestion?.image}'), + controller: context.read().imageAnimationController, + child: AnswerPictureBox( selected: false, + showIndex: false, correctAnswer: 0, index: 0, image: state.currentQuestion?.image ?? '', @@ -128,75 +128,73 @@ class _QuestionScreenState extends State with TickerProviderStat Widget _titles(BuildContext context) { return BlocBuilder( buildWhen: (previous, current) => - previous.currentQuestion?.id != current.currentQuestion?.id, - builder: (context, state) => - FadeAnim( - child: SizedBox( - height: 100, - child: ListView( - controller: context.read().titleController, - children: [ - Text( - state.currentQuestion?.title ?? '', - textAlign: TextAlign.center, - style: MYTextStyle.titr1.copyWith( - shadows: [ - BoxShadow( - offset: Offset(0, 2), - color: MyColors.black.withValues(alpha: 0.25), - ), - ], - ), - ), - ], + previous.currentQuestion?.id != current.currentQuestion?.id, + builder: (context, state) => FadeAnimController( + controller: context.read().answerAnimationController, + child: Text( + state.currentQuestion?.title ?? '', + textAlign: TextAlign.center, + style: MYTextStyle.titr1.copyWith( + shadows: [ + BoxShadow( + offset: Offset(0, 2), + color: MyColors.black.withValues(alpha: 0.25), ), - ), + ], ), + ), + ), ); } Widget _answers(BuildContext context) { - return BlocBuilder( - buildWhen: (previous, current) => - previous.currentQuestion?.id != current.currentQuestion?.id, - builder: (context, state) => GridView.builder( - itemCount: state.currentQuestion?.answers?.length ?? 0, - physics: NeverScrollableScrollPhysics(), - shrinkWrap: true, - clipBehavior: Clip.none, - padding: EdgeInsets.symmetric( - horizontal: setSize(context: context, tablet: 70) ?? 0, - ), - gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: 2, - crossAxisSpacing: MySpaces.s20, - mainAxisSpacing: 20, - childAspectRatio: 0.75, + return ListView( + children: [ + _titles(context), + 30.0.gapHeight, + BlocBuilder( + buildWhen: (previous, current) => + previous.currentQuestion?.id != current.currentQuestion?.id, + builder: (context, state) => GridView.builder( + itemCount: state.currentQuestion?.answers?.length ?? 0, + physics: NeverScrollableScrollPhysics(), + shrinkWrap: true, + clipBehavior: Clip.none, + padding: EdgeInsets.symmetric( + horizontal: setSize(context: context, tablet: 70) ?? 0, + ), + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 2, + crossAxisSpacing: MySpaces.s20, + mainAxisSpacing: 20, + childAspectRatio: 0.75, + ), + itemBuilder: (context, index) => + state.currentQuestion?.answers?[index].imageId == null + ? SizedBox.shrink() + : SlideAnim( + key: Key('${state.currentQuestion?.id}'), + controller: context.read().answerAnimationController, + index: index, + child: AnswerBox( + index: state.currentQuestion?.answers?[index].order ?? 1, + answer: state.currentQuestion?.answers?[index] ?? AnswerEntity(), + correctAnswer: state.currentQuestion?.correctAnswer ?? 0, + onNotifTap: (AnswerEntity answer) { + context.read().showAnswerDialog( + context: context, + answerEntity: answer, + ); + }, + onTap: (isCorrect, correctAnswer) => + context.read().add( + ChooseAnswerEvent(isCorrect, correctAnswer, context), + ), + ), + ), + ), ), - itemBuilder: (context, index) => - state.currentQuestion?.answers?[index].imageId == null - ? SizedBox.shrink() - : SlideAnim( - key: Key('${state.currentQuestion?.id}'), - controller: context.read().answerAnimationController, - index: index, - child: AnswerBox( - index: state.currentQuestion?.answers?[index].order ?? 1, - answer: state.currentQuestion?.answers?[index] ?? AnswerEntity(), - correctAnswer: state.currentQuestion?.correctAnswer ?? 0, - onNotifTap: (AnswerEntity answer) { - context.read().showAnswerDialog( - context: context, - answerEntity: answer, - ); - }, - onTap: (isCorrect, correctAnswer) => - context.read().add( - ChooseAnswerEvent(isCorrect, correctAnswer, context), - ), - ), - ), - ), + ], ); } diff --git a/lib/features/splash/presentation/bloc/splash_bloc.dart b/lib/features/splash/presentation/bloc/splash_bloc.dart index 5fc686b..b4270a2 100644 --- a/lib/features/splash/presentation/bloc/splash_bloc.dart +++ b/lib/features/splash/presentation/bloc/splash_bloc.dart @@ -1,8 +1,8 @@ import 'package:bloc/bloc.dart'; import 'package:flutter/cupertino.dart'; import 'package:go_router/go_router.dart'; -import 'package:hadi_hoda_flutter/common_ui/resources/my_assets.dart'; import 'package:hadi_hoda_flutter/core/routers/my_routes.dart'; +import 'package:hadi_hoda_flutter/core/utils/pre_cache_image.dart'; import 'package:hadi_hoda_flutter/features/splash/presentation/bloc/splash_event.dart'; import 'package:hadi_hoda_flutter/features/splash/presentation/bloc/splash_state.dart'; @@ -17,19 +17,9 @@ class SplashBloc extends Bloc { /// ------------Controllers------------ /// ------------Functions------------ - Future _precacheAllImages(BuildContext context) async { - await Future.wait( - MyAssets.images.map( - (assetPath) => precacheImage(AssetImage(assetPath), context), - ), - ); - } Future goToHomePage(BuildContext context) async { - if (context.mounted) { - await _precacheAllImages(context); - } - + await preCacheImages(); await Future.delayed( Duration(seconds: 2), () { diff --git a/pubspec.yaml b/pubspec.yaml index 0ecdc83..5be1773 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: hadi_hoda_flutter description: "A new Flutter project." publish_to: 'none' -version: 0.2.0+1 +version: 0.2.1+1 environment: sdk: ^3.9.2 @@ -51,6 +51,7 @@ flutter: - assets/images/ - assets/animations/ - assets/audios/ + - assets/videos/ - path: assets/svg/ transformers: - package: vector_graphics_compiler