Browse Source

add: gifs

pull/66/head
AmirrezaChegini 1 week ago
parent
commit
73e0f1a04e
  1. BIN
      assets/videos/globe_state_after_wrong.gif
  2. BIN
      assets/videos/globe_state_normal.gif
  3. BIN
      assets/videos/globe_state_speaking.gif
  4. BIN
      assets/videos/globe_state_success.gif
  5. BIN
      assets/videos/globe_state_wrong.gif
  6. 5
      lib/common_ui/resources/my_animations.dart
  7. 38
      lib/features/question/presentation/bloc/question_bloc.dart
  8. 36
      lib/features/question/presentation/ui/screens/question_screen.dart

BIN
assets/videos/globe_state_after_wrong.gif

After

Width: 320  |  Height: 320  |  Size: 2.7 MiB

BIN
assets/videos/globe_state_normal.gif

After

Width: 320  |  Height: 320  |  Size: 2.7 MiB

BIN
assets/videos/globe_state_speaking.gif

After

Width: 320  |  Height: 320  |  Size: 2.2 MiB

BIN
assets/videos/globe_state_success.gif

After

Width: 320  |  Height: 320  |  Size: 2.9 MiB

BIN
assets/videos/globe_state_wrong.gif

After

Width: 320  |  Height: 320  |  Size: 2.8 MiB

5
lib/common_ui/resources/my_animations.dart

@ -5,4 +5,9 @@ class MyAnimations {
static const String confetti = 'assets/animations/confetti.json'; static const String confetti = 'assets/animations/confetti.json';
static const String lightPurple = 'assets/animations/lights_purple.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';
} }

38
lib/features/question/presentation/bloc/question_bloc.dart

@ -3,6 +3,7 @@ import 'dart:async';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:go_router/go_router.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/common_ui/resources/my_audios.dart';
import 'package:hadi_hoda_flutter/core/constants/my_constants.dart'; import 'package:hadi_hoda_flutter/core/constants/my_constants.dart';
import 'package:hadi_hoda_flutter/core/params/question_params.dart'; import 'package:hadi_hoda_flutter/core/params/question_params.dart';
@ -44,6 +45,7 @@ class QuestionBloc extends Bloc<QuestionEvent, QuestionState> {
_backgroundAudioService.dispose(); _backgroundAudioService.dispose();
answerAnimationController?.dispose(); answerAnimationController?.dispose();
imageAnimationController?.dispose(); imageAnimationController?.dispose();
globeAnimationController?.dispose();
scrollController.dispose(); scrollController.dispose();
return super.close(); return super.close();
} }
@ -66,6 +68,20 @@ class QuestionBloc extends Bloc<QuestionEvent, QuestionState> {
'hadith_key': GlobalKey(), 'hadith_key': GlobalKey(),
'guide_key': GlobalKey(), 'guide_key': GlobalKey(),
}; };
final Map<String, double> globeStates = {
MyAnimations.globeStateSpeaking: 0,
MyAnimations.globeStateNormal: 0.25,
MyAnimations.globeStateSuccess: 0.5,
MyAnimations.globeStateWrong: 0.75,
MyAnimations.globeStateAfterWrong: 1,
};
final Map<double, String> statesGlobe = {
0: MyAnimations.globeStateSpeaking,
0.25: MyAnimations.globeStateNormal,
0.5: MyAnimations.globeStateSuccess,
0.75: MyAnimations.globeStateWrong,
1: MyAnimations.globeStateAfterWrong,
};
Stream<double>? volumeStream; Stream<double>? volumeStream;
bool showAnswerSequence = true; bool showAnswerSequence = true;
@ -75,6 +91,7 @@ class QuestionBloc extends Bloc<QuestionEvent, QuestionState> {
final AudioService _effectAudioService; final AudioService _effectAudioService;
AnimationController? answerAnimationController; AnimationController? answerAnimationController;
AnimationController? imageAnimationController; AnimationController? imageAnimationController;
AnimationController? globeAnimationController;
final ScrollController scrollController = ScrollController(); final ScrollController scrollController = ScrollController();
/// ------------Functions------------ /// ------------Functions------------
@ -163,6 +180,7 @@ class QuestionBloc extends Bloc<QuestionEvent, QuestionState> {
} }
}); });
} }
changeGlobeState(key: MyAnimations.globeStateNormal);
} }
Future<void> showAnswerDialog({ Future<void> showAnswerDialog({
@ -172,6 +190,9 @@ class QuestionBloc extends Bloc<QuestionEvent, QuestionState> {
bool showConfetti = false, bool showConfetti = false,
bool autoClose = true, bool autoClose = true,
}) async { }) async {
if(showConfetti == false){
changeGlobeState(key: MyAnimations.globeStateSpeaking);
}
await Navigator.of(context).push( await Navigator.of(context).push(
HeroDialogRoute( HeroDialogRoute(
builder: (dialogContext) { builder: (dialogContext) {
@ -184,6 +205,7 @@ class QuestionBloc extends Bloc<QuestionEvent, QuestionState> {
}, },
), ),
); );
changeGlobeState(key: MyAnimations.globeStateNormal);
} }
Future<void> getNextLevelEvent({required BuildContext context}) async { Future<void> getNextLevelEvent({required BuildContext context}) async {
@ -213,6 +235,15 @@ class QuestionBloc extends Bloc<QuestionEvent, QuestionState> {
await _backgroundAudioService.play(); await _backgroundAudioService.play();
} }
void changeGlobeState({String? key}) {
if (key?.isEmpty ?? true) return;
globeAnimationController?.animateTo(
globeStates[key] ?? 0,
duration: const Duration(milliseconds: 0),
);
}
/// ------------Event Calls------------ /// ------------Event Calls------------
FutureOr<void> _getLevelEvent(GetLevelEvent event, Emitter<QuestionState> emit) async { FutureOr<void> _getLevelEvent(GetLevelEvent event, Emitter<QuestionState> emit) async {
await _getLevelUseCase(QuestionParams(id: int.parse(event.id ?? '0'))).then( await _getLevelUseCase(QuestionParams(id: int.parse(event.id ?? '0'))).then(
@ -236,6 +267,7 @@ class QuestionBloc extends Bloc<QuestionEvent, QuestionState> {
correctAnswer: false, correctAnswer: false,
)); ));
imageAnimationController?.forward(); imageAnimationController?.forward();
changeGlobeState(key: MyAnimations.globeStateSpeaking);
await playQuestionAudio(); await playQuestionAudio();
imageAnimationController?.reverse(); imageAnimationController?.reverse();
answerAnimationController?.forward().then((value) { answerAnimationController?.forward().then((value) {
@ -255,6 +287,7 @@ class QuestionBloc extends Bloc<QuestionEvent, QuestionState> {
emit(state.copyWith(correctAnswer: event.chooseCorrectAnswer)); emit(state.copyWith(correctAnswer: event.chooseCorrectAnswer));
if (event.chooseCorrectAnswer) { if (event.chooseCorrectAnswer) {
changeGlobeState(key: MyAnimations.globeStateSuccess);
await showAnswerDialog( await showAnswerDialog(
context: MyContext.get, context: MyContext.get,
correctAudio: state.currentQuestion?.correctAudio, correctAudio: state.currentQuestion?.correctAudio,
@ -288,6 +321,7 @@ class QuestionBloc extends Bloc<QuestionEvent, QuestionState> {
await Future.delayed(const Duration(seconds: 1)); await Future.delayed(const Duration(seconds: 1));
imageAnimationController?.forward(); imageAnimationController?.forward();
scrollController.jumpTo(0); scrollController.jumpTo(0);
changeGlobeState(key: MyAnimations.globeStateSpeaking);
await playQuestionAudio(); await playQuestionAudio();
imageAnimationController?.reverse(); imageAnimationController?.reverse();
answerAnimationController?.forward().then((value) { answerAnimationController?.forward().then((value) {
@ -296,7 +330,11 @@ class QuestionBloc extends Bloc<QuestionEvent, QuestionState> {
} }
}); });
} else { } else {
changeGlobeState(key: MyAnimations.globeStateWrong);
playWrongAudio(); playWrongAudio();
await Future.delayed(const Duration(milliseconds: 1500), () {
changeGlobeState(key: MyAnimations.globeStateAfterWrong);
});
} }
} }
} }

36
lib/features/question/presentation/ui/screens/question_screen.dart

@ -1,6 +1,8 @@
import 'package:auto_size_text/auto_size_text.dart'; import 'package:auto_size_text/auto_size_text.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.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_assets.dart';
import 'package:hadi_hoda_flutter/common_ui/resources/my_colors.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/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/local_storage.dart';
import 'package:hadi_hoda_flutter/core/utils/my_localization.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/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.dart';
import 'package:hadi_hoda_flutter/core/widgets/animations/fade_anim_controller.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/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_anim.dart';
import 'package:hadi_hoda_flutter/core/widgets/animations/slide_up_fade.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/answer_box.dart';
import 'package:hadi_hoda_flutter/core/widgets/answer_box/styles/image_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/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_bloc.dart';
import 'package:hadi_hoda_flutter/features/question/presentation/bloc/question_event.dart'; import 'package:hadi_hoda_flutter/features/question/presentation/bloc/question_event.dart';
@ -55,6 +54,11 @@ class _QuestionScreenState extends State<QuestionScreen>
if (LocalStorage.readData(key: MyConstants.firstShowcase) == 'true') { if (LocalStorage.readData(key: MyConstants.firstShowcase) == 'true') {
context.read<QuestionBloc>().imageAnimationController?.forward(); context.read<QuestionBloc>().imageAnimationController?.forward();
} }
context.read<QuestionBloc>().globeAnimationController = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 500),
reverseDuration: const Duration(milliseconds: 500),
);
} }
@override @override
@ -451,12 +455,25 @@ class _QuestionScreenState extends State<QuestionScreen>
child: Stack( child: Stack(
alignment: AlignmentDirectional.centerStart, alignment: AlignmentDirectional.centerStart,
children: [ children: [
GlobeAnimation(
child: MyImage(
image: MyAssets.globe,
fit: BoxFit.cover,
size: setSize(context: context, tablet: 120),
),
AnimatedBuilder(
animation: context
.read<QuestionBloc>()
.globeAnimationController!,
builder: (context, child) =>
Gif(
image: AssetImage(context
.read<QuestionBloc>()
.statesGlobe[context
.read<QuestionBloc>()
.globeAnimationController
?.value ??
0] ??
MyAnimations.globeStateSpeaking),
fps: 10,
autostart: Autostart.loop,
width: 80,
height: 80,
)
), ),
Positioned( Positioned(
left: 90, left: 90,
@ -484,6 +501,7 @@ class _QuestionScreenState extends State<QuestionScreen>
show: false, show: false,
); );
context.read<QuestionBloc>().pausePlaying(); context.read<QuestionBloc>().pausePlaying();
context.read<QuestionBloc>().changeGlobeState(key: MyAnimations.globeStateNormal);
} }
}, },
style: TextButton.styleFrom( style: TextButton.styleFrom(

Loading…
Cancel
Save