diff --git a/lib/core/routers/hero_dialog_route.dart b/lib/core/routers/hero_dialog_route.dart index 883cb25..54a199f 100644 --- a/lib/core/routers/hero_dialog_route.dart +++ b/lib/core/routers/hero_dialog_route.dart @@ -16,13 +16,13 @@ class HeroDialogRoute extends PageRoute { bool get fullscreenDialog => false; @override - bool get barrierDismissible => true; + bool get barrierDismissible => false; @override Duration get transitionDuration => const Duration(seconds: 1); // Adjust as needed @override - bool get maintainState => true; + bool get maintainState => false; @override Color get barrierColor => Color(0XFF322386).withValues(alpha: 0.3); // Or your desired barrier color diff --git a/lib/core/services/audio_service.dart b/lib/core/services/audio_service.dart index 0bd3def..bb54fcf 100644 --- a/lib/core/services/audio_service.dart +++ b/lib/core/services/audio_service.dart @@ -29,6 +29,9 @@ class AudioService { Future play() async { try { await _player.play(); + await _player.processingStateStream + .firstWhere((s) => s == ProcessingState.completed); + return; } catch (e) { if (kDebugMode) { print('$e'); diff --git a/lib/features/question/presentation/bloc/question_bloc.dart b/lib/features/question/presentation/bloc/question_bloc.dart index 9c05cdb..71ec7e0 100644 --- a/lib/features/question/presentation/bloc/question_bloc.dart +++ b/lib/features/question/presentation/bloc/question_bloc.dart @@ -40,7 +40,7 @@ class QuestionBloc extends Bloc { @override Future close() { - ShowcaseView.get().unregister(); + unRegisterShowCase(); return super.close(); } @@ -63,7 +63,6 @@ class QuestionBloc extends Bloc { 'guide_key': GlobalKey(), }; late final Stream volumeStream; - bool isPlaying = false; /// ------------Controllers------------ final AudioService _mainAudioService; @@ -71,27 +70,37 @@ class QuestionBloc extends Bloc { /// ------------Functions------------ void registerShowCase() { - ShowcaseView.register( - onStart: (showcaseIndex, key) { - LocalStorage.saveData(key: MyConstants.firstShowcase, value: 'true'); - }, - ); + try { + ShowcaseView.register( + onStart: (showcaseIndex, key) { + LocalStorage.saveData(key: MyConstants.firstShowcase, value: 'true'); + }, + ); + } catch (_) {} } + void unRegisterShowCase() { + try { + ShowcaseView.get().unregister(); + } catch (_) {} + } + + void startShowcase() { if (LocalStorage.readData(key: MyConstants.firstShowcase) != 'true') { - ShowcaseView.get().startShowCase([ - showCaseKey['answer_key_1']!, - showCaseKey['notif_key_0']!, - showCaseKey['stepper_key']!, - showCaseKey['hadith_key']!, - showCaseKey['guide_key']!, - ]); + try { + ShowcaseView.get().startShowCase([ + showCaseKey['answer_key_1']!, + showCaseKey['notif_key_0']!, + showCaseKey['stepper_key']!, + showCaseKey['hadith_key']!, + showCaseKey['guide_key']!, + ]); + } catch (_) {} } } void showHadith({required BuildContext context}) { - if(isPlaying) return; showHadithDialog( context: context, hadith: state.levelEntity?.hadith ?? [], @@ -112,8 +121,10 @@ class QuestionBloc extends Bloc { } Future stopMusic() async { - await _mainAudioService.stop(); - await _mainAudioService.setLoopMode(isLoop: false); + await Future.wait([ + _mainAudioService.stop(), + _mainAudioService.setLoopMode(isLoop: false), + ]); } Future playCorrectAudio() async { @@ -134,6 +145,7 @@ class QuestionBloc extends Bloc { Future playQuestionAudio() async { await _mainAudioService.setAudio(filePath: state.currentQuestion?.audio); await _mainAudioService.play(); + await showQueueAnswer(); } Future changeMute() async { @@ -143,21 +155,41 @@ class QuestionBloc extends Bloc { ]); } + Future showQueueAnswer() async { + final List answers = state.currentQuestion?.answers ?? []; + if (answers.isNotEmpty) { + answers.removeWhere((e) => e.imageId == null); + } + for (final answer in answers) { + await Future.delayed(const Duration(milliseconds: 500), () async { + if (MyContext.get.mounted) { + await showAnswerDialog( + context: MyContext.get, + answerEntity: answer, + autoClose: true, + ); + } + }); + } + } + Future showAnswerDialog({ required BuildContext context, required AnswerEntity answerEntity, + bool showConfetti = false, + bool autoClose = false, }) async { - Navigator.of(context).push( + await Navigator.of(context).push( HeroDialogRoute( builder: (dialogContext) { return AnswerScreen( answerEntity: answerEntity, - onNotifTap: (answer) => playAnswerAudio(audio: answer.audio), + showConfetti: showConfetti, + autoClose: autoClose, ); }, ), ); - playAnswerAudio(audio: answerEntity.audio); } Future getNextLevelEvent({required BuildContext context}) async { @@ -213,16 +245,11 @@ class QuestionBloc extends Bloc { if (event.chooseCorrectAnswer) { playCorrectAudio(); - await Navigator.of(MyContext.get).push( - HeroDialogRoute( - builder: (dialogContext) { - return AnswerScreen( - answerEntity: state.currentQuestion?.answers?.singleWhere((e) => - e.order == event.correctAnswer) ?? AnswerEntity(), - showConfetti: true, - ); - }, - ), + await showAnswerDialog( + context: MyContext.get, + answerEntity: state.currentQuestion?.answers?.singleWhere((e) => + e.order == event.correctAnswer) ?? AnswerEntity(), + showConfetti: true, ); await Future.delayed(Duration(seconds: 1), () async { final QuestionEntity? findPreQuestion = state.currentQuestion; @@ -245,7 +272,7 @@ class QuestionBloc extends Bloc { ); } } else { - playQuestionAudio(); + await playQuestionAudio(); } }); } else { diff --git a/lib/features/question/presentation/ui/screens/answer_screen.dart b/lib/features/question/presentation/ui/screens/answer_screen.dart index 721730e..6fce216 100644 --- a/lib/features/question/presentation/ui/screens/answer_screen.dart +++ b/lib/features/question/presentation/ui/screens/answer_screen.dart @@ -1,50 +1,74 @@ import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:hadi_hoda_flutter/common_ui/resources/my_animations.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/constants/my_constants.dart'; +import 'package:hadi_hoda_flutter/core/services/audio_service.dart'; import 'package:hadi_hoda_flutter/core/utils/my_context.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/utils/set_platform_size.dart'; import 'package:hadi_hoda_flutter/core/widgets/answer_box/answer_box_show.dart'; import 'package:hadi_hoda_flutter/features/question/domain/entity/answer_entity.dart'; +import 'package:hadi_hoda_flutter/init_bindings.dart'; import 'package:lottie/lottie.dart'; class AnswerScreen extends StatefulWidget { const AnswerScreen({ super.key, required this.answerEntity, - this.onNotifTap, - this.showConfetti = false, + required this.showConfetti, + required this.autoClose, }); final AnswerEntity answerEntity; - final Function(AnswerEntity answer)? onNotifTap; final bool showConfetti; + final bool autoClose; @override State createState() => _AnswerScreenState(); } class _AnswerScreenState extends State { + + final AudioService audioService = locator( + instanceName: MyConstants.mainAudioService, + ); + @override void initState() { super.initState(); - back(); + initWidget(); } - Future back() async { + Future initWidget() async { if (widget.showConfetti) { await Future.delayed(Duration(seconds: 3), () { - if (MyContext.get.mounted) { + if (MyContext.get.mounted && MyContext.get.canPop()) { MyContext.get.pop(); } }); + } else { + await playAudio(); + if (widget.autoClose) { + if (MyContext.get.mounted && MyContext.get.canPop()) { + MyContext.get.pop(); + } + } } } + Future playAudio() async { + await audioService.setAudio(filePath: widget.answerEntity.audio); + await audioService.play(); + } + @override Widget build(BuildContext context) { return Stack( + alignment: Alignment.center, children: [ Center( child: Padding( @@ -56,7 +80,22 @@ class _AnswerScreenState extends State { child: AnswerBoxShow( answer: widget.answerEntity, index: widget.answerEntity.order ?? 0, - onNotifTap: widget.onNotifTap, + onNotifTap: (answer) => playAudio(), + ), + ), + ), + Positioned( + bottom: setPlatform(android: MySpaces.s30), + child: TextButton( + onPressed: () { + context.pop(); + }, + style: TextButton.styleFrom( + foregroundColor: MyColors.white.withValues(alpha: 0.7), + ), + child: Text( + context.translate.skip, + style: MYTextStyle.button2 ), ), ), diff --git a/lib/features/question/presentation/ui/screens/question_screen.dart b/lib/features/question/presentation/ui/screens/question_screen.dart index f2ec930..4a1a345 100644 --- a/lib/features/question/presentation/ui/screens/question_screen.dart +++ b/lib/features/question/presentation/ui/screens/question_screen.dart @@ -135,7 +135,7 @@ class QuestionScreen extends StatelessWidget { child: SizedBox( width: context.widthScreen, child: Stack( - alignment: Alignment.center, + alignment: AlignmentDirectional.centerStart, children: [ MyShowcaseWidget( globalKey: context.read().showCaseKey['guide_key']!,