diff --git a/assets/videos/globe_state_after_wrong.gif b/assets/videos/globe_state_after_wrong.gif new file mode 100644 index 0000000..60070d6 Binary files /dev/null and b/assets/videos/globe_state_after_wrong.gif differ diff --git a/assets/videos/globe_state_normal.gif b/assets/videos/globe_state_normal.gif new file mode 100644 index 0000000..2b22c94 Binary files /dev/null and b/assets/videos/globe_state_normal.gif differ diff --git a/assets/videos/globe_state_speaking.gif b/assets/videos/globe_state_speaking.gif new file mode 100644 index 0000000..edf88b0 Binary files /dev/null and b/assets/videos/globe_state_speaking.gif differ diff --git a/assets/videos/globe_state_success.gif b/assets/videos/globe_state_success.gif new file mode 100644 index 0000000..4c41ce3 Binary files /dev/null and b/assets/videos/globe_state_success.gif differ diff --git a/assets/videos/globe_state_wrong.gif b/assets/videos/globe_state_wrong.gif new file mode 100644 index 0000000..845abf5 Binary files /dev/null and b/assets/videos/globe_state_wrong.gif differ diff --git a/lib/common_ui/resources/my_animations.dart b/lib/common_ui/resources/my_animations.dart index 5739d3d..c465553 100644 --- a/lib/common_ui/resources/my_animations.dart +++ b/lib/common_ui/resources/my_animations.dart @@ -5,4 +5,9 @@ class MyAnimations { static const String confetti = 'assets/animations/confetti.json'; static const String lightPurple = 'assets/animations/lights_purple.json'; + static const String globeStateAfterWrong = 'assets/videos/globe_state_after_wrong.gif'; + static const String globeStateNormal = 'assets/videos/globe_state_normal.gif'; + static const String globeStateSpeaking = 'assets/videos/globe_state_speaking.gif'; + static const String globeStateSuccess = 'assets/videos/globe_state_success.gif'; + static const String globeStateWrong = 'assets/videos/globe_state_wrong.gif'; } \ No newline at end of file diff --git a/lib/features/question/presentation/bloc/question_bloc.dart b/lib/features/question/presentation/bloc/question_bloc.dart index 343b7d5..33098df 100644 --- a/lib/features/question/presentation/bloc/question_bloc.dart +++ b/lib/features/question/presentation/bloc/question_bloc.dart @@ -3,6 +3,7 @@ import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.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_audios.dart'; import 'package:hadi_hoda_flutter/core/constants/my_constants.dart'; import 'package:hadi_hoda_flutter/core/params/question_params.dart'; @@ -44,6 +45,7 @@ class QuestionBloc extends Bloc { _backgroundAudioService.dispose(); answerAnimationController?.dispose(); imageAnimationController?.dispose(); + globeAnimationController?.dispose(); scrollController.dispose(); return super.close(); } @@ -66,6 +68,20 @@ class QuestionBloc extends Bloc { 'hadith_key': GlobalKey(), 'guide_key': GlobalKey(), }; + final Map globeStates = { + MyAnimations.globeStateSpeaking: 0, + MyAnimations.globeStateNormal: 0.25, + MyAnimations.globeStateSuccess: 0.5, + MyAnimations.globeStateWrong: 0.75, + MyAnimations.globeStateAfterWrong: 1, + }; + final Map statesGlobe = { + 0: MyAnimations.globeStateSpeaking, + 0.25: MyAnimations.globeStateNormal, + 0.5: MyAnimations.globeStateSuccess, + 0.75: MyAnimations.globeStateWrong, + 1: MyAnimations.globeStateAfterWrong, + }; Stream? volumeStream; bool showAnswerSequence = true; @@ -75,6 +91,7 @@ class QuestionBloc extends Bloc { final AudioService _effectAudioService; AnimationController? answerAnimationController; AnimationController? imageAnimationController; + AnimationController? globeAnimationController; final ScrollController scrollController = ScrollController(); /// ------------Functions------------ @@ -163,6 +180,7 @@ class QuestionBloc extends Bloc { } }); } + changeGlobeState(key: MyAnimations.globeStateNormal); } Future showAnswerDialog({ @@ -172,6 +190,9 @@ class QuestionBloc extends Bloc { bool showConfetti = false, bool autoClose = true, }) async { + if(showConfetti == false){ + changeGlobeState(key: MyAnimations.globeStateSpeaking); + } await Navigator.of(context).push( HeroDialogRoute( builder: (dialogContext) { @@ -184,6 +205,7 @@ class QuestionBloc extends Bloc { }, ), ); + changeGlobeState(key: MyAnimations.globeStateNormal); } Future getNextLevelEvent({required BuildContext context}) async { @@ -213,6 +235,15 @@ class QuestionBloc extends Bloc { await _backgroundAudioService.play(); } + void changeGlobeState({String? key}) { + if (key?.isEmpty ?? true) return; + + globeAnimationController?.animateTo( + globeStates[key] ?? 0, + duration: const Duration(milliseconds: 0), + ); + } + /// ------------Event Calls------------ FutureOr _getLevelEvent(GetLevelEvent event, Emitter emit) async { await _getLevelUseCase(QuestionParams(id: int.parse(event.id ?? '0'))).then( @@ -236,6 +267,7 @@ class QuestionBloc extends Bloc { correctAnswer: false, )); imageAnimationController?.forward(); + changeGlobeState(key: MyAnimations.globeStateSpeaking); await playQuestionAudio(); imageAnimationController?.reverse(); answerAnimationController?.forward().then((value) { @@ -255,6 +287,7 @@ class QuestionBloc extends Bloc { emit(state.copyWith(correctAnswer: event.chooseCorrectAnswer)); if (event.chooseCorrectAnswer) { + changeGlobeState(key: MyAnimations.globeStateSuccess); await showAnswerDialog( context: MyContext.get, correctAudio: state.currentQuestion?.correctAudio, @@ -288,6 +321,7 @@ class QuestionBloc extends Bloc { await Future.delayed(const Duration(seconds: 1)); imageAnimationController?.forward(); scrollController.jumpTo(0); + changeGlobeState(key: MyAnimations.globeStateSpeaking); await playQuestionAudio(); imageAnimationController?.reverse(); answerAnimationController?.forward().then((value) { @@ -296,7 +330,11 @@ class QuestionBloc extends Bloc { } }); } else { + changeGlobeState(key: MyAnimations.globeStateWrong); playWrongAudio(); + await Future.delayed(const Duration(milliseconds: 1500), () { + changeGlobeState(key: MyAnimations.globeStateAfterWrong); + }); } } } diff --git a/lib/features/question/presentation/ui/screens/question_screen.dart b/lib/features/question/presentation/ui/screens/question_screen.dart index a08b345..738782b 100644 --- a/lib/features/question/presentation/ui/screens/question_screen.dart +++ b/lib/features/question/presentation/ui/screens/question_screen.dart @@ -1,6 +1,8 @@ import 'package:auto_size_text/auto_size_text.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:gif/gif.dart'; +import 'package:hadi_hoda_flutter/common_ui/resources/my_animations.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'; @@ -9,16 +11,13 @@ import 'package:hadi_hoda_flutter/core/utils/gap.dart'; import 'package:hadi_hoda_flutter/core/utils/local_storage.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/animations/fade_anim.dart'; import 'package:hadi_hoda_flutter/core/widgets/animations/fade_anim_controller.dart'; import 'package:hadi_hoda_flutter/core/widgets/animations/fade_anim_delayed.dart'; -import 'package:hadi_hoda_flutter/core/widgets/animations/globe_animation.dart'; import 'package:hadi_hoda_flutter/core/widgets/animations/slide_anim.dart'; import 'package:hadi_hoda_flutter/core/widgets/animations/slide_up_fade.dart'; import 'package:hadi_hoda_flutter/core/widgets/answer_box/answer_box.dart'; import 'package:hadi_hoda_flutter/core/widgets/answer_box/styles/image_box.dart'; -import 'package:hadi_hoda_flutter/core/widgets/images/my_image.dart'; import 'package:hadi_hoda_flutter/features/question/domain/entity/answer_entity.dart'; import 'package:hadi_hoda_flutter/features/question/presentation/bloc/question_bloc.dart'; import 'package:hadi_hoda_flutter/features/question/presentation/bloc/question_event.dart'; @@ -55,6 +54,11 @@ class _QuestionScreenState extends State if (LocalStorage.readData(key: MyConstants.firstShowcase) == 'true') { context.read().imageAnimationController?.forward(); } + context.read().globeAnimationController = AnimationController( + vsync: this, + duration: const Duration(milliseconds: 500), + reverseDuration: const Duration(milliseconds: 500), + ); } @override @@ -451,12 +455,25 @@ class _QuestionScreenState extends State child: Stack( alignment: AlignmentDirectional.centerStart, children: [ - GlobeAnimation( - child: MyImage( - image: MyAssets.globe, - fit: BoxFit.cover, - size: setSize(context: context, tablet: 120), - ), + AnimatedBuilder( + animation: context + .read() + .globeAnimationController!, + builder: (context, child) => + Gif( + image: AssetImage(context + .read() + .statesGlobe[context + .read() + .globeAnimationController + ?.value ?? + 0] ?? + MyAnimations.globeStateSpeaking), + fps: 10, + autostart: Autostart.loop, + width: 80, + height: 80, + ) ), Positioned( left: 90, @@ -484,6 +501,7 @@ class _QuestionScreenState extends State show: false, ); context.read().pausePlaying(); + context.read().changeGlobeState(key: MyAnimations.globeStateNormal); } }, style: TextButton.styleFrom(