|
|
@ -40,6 +40,7 @@ class QuestionBloc extends Bloc<QuestionEvent, QuestionState> { |
|
|
|
|
|
|
|
|
@override |
|
|
@override |
|
|
Future<void> close() { |
|
|
Future<void> close() { |
|
|
|
|
|
_sequenceToken++; |
|
|
if (!_mainAudioService.isMuted) { |
|
|
if (!_mainAudioService.isMuted) { |
|
|
_mainAudioService.setVolume(volume: MyConstants.musicAudioVolume); |
|
|
_mainAudioService.setVolume(volume: MyConstants.musicAudioVolume); |
|
|
} |
|
|
} |
|
|
@ -56,19 +57,19 @@ class QuestionBloc extends Bloc<QuestionEvent, QuestionState> { |
|
|
final GetNextLevelUseCase _getNextLevelUseCase; |
|
|
final GetNextLevelUseCase _getNextLevelUseCase; |
|
|
|
|
|
|
|
|
/// ------------Variables------------ |
|
|
/// ------------Variables------------ |
|
|
final Map<String, GlobalKey> showCaseKey = { |
|
|
|
|
|
'answer_key_0': GlobalKey(), |
|
|
|
|
|
'answer_key_1': GlobalKey(), |
|
|
|
|
|
'answer_key_2': GlobalKey(), |
|
|
|
|
|
'answer_key_3': GlobalKey(), |
|
|
|
|
|
'notif_key_0': GlobalKey(), |
|
|
|
|
|
'notif_key_1': GlobalKey(), |
|
|
|
|
|
'notif_key_2': GlobalKey(), |
|
|
|
|
|
'notif_key_3': GlobalKey(), |
|
|
|
|
|
'stepper_key': GlobalKey(), |
|
|
|
|
|
'hadith_key': GlobalKey(), |
|
|
|
|
|
'guide_key': GlobalKey(), |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
// final Map<String, GlobalKey> showCaseKey = { |
|
|
|
|
|
// 'answer_key_0': GlobalKey(), |
|
|
|
|
|
// 'answer_key_1': GlobalKey(), |
|
|
|
|
|
// 'answer_key_2': GlobalKey(), |
|
|
|
|
|
// 'answer_key_3': GlobalKey(), |
|
|
|
|
|
// 'notif_key_0': GlobalKey(), |
|
|
|
|
|
// 'notif_key_1': GlobalKey(), |
|
|
|
|
|
// 'notif_key_2': GlobalKey(), |
|
|
|
|
|
// 'notif_key_3': GlobalKey(), |
|
|
|
|
|
// 'stepper_key': GlobalKey(), |
|
|
|
|
|
// 'hadith_key': GlobalKey(), |
|
|
|
|
|
// 'guide_key': GlobalKey(), |
|
|
|
|
|
// }; |
|
|
final Map<String, double> globeStates = { |
|
|
final Map<String, double> globeStates = { |
|
|
MyAnimations.globeStateSpeaking: 0, |
|
|
MyAnimations.globeStateSpeaking: 0, |
|
|
MyAnimations.globeStateNormal: 0.25, |
|
|
MyAnimations.globeStateNormal: 0.25, |
|
|
@ -86,6 +87,7 @@ class QuestionBloc extends Bloc<QuestionEvent, QuestionState> { |
|
|
Stream<double>? volumeStream; |
|
|
Stream<double>? volumeStream; |
|
|
bool showAnswerSequence = true; |
|
|
bool showAnswerSequence = true; |
|
|
bool isHadithDialogOpen = false; |
|
|
bool isHadithDialogOpen = false; |
|
|
|
|
|
int _sequenceToken = 0; |
|
|
|
|
|
|
|
|
/// ------------Controllers------------ |
|
|
/// ------------Controllers------------ |
|
|
final AudioService _mainAudioService; |
|
|
final AudioService _mainAudioService; |
|
|
@ -96,6 +98,10 @@ class QuestionBloc extends Bloc<QuestionEvent, QuestionState> { |
|
|
AnimationController? globeAnimationController; |
|
|
AnimationController? globeAnimationController; |
|
|
final ScrollController scrollController = ScrollController(); |
|
|
final ScrollController scrollController = ScrollController(); |
|
|
|
|
|
|
|
|
|
|
|
int _nextSequenceToken() => ++_sequenceToken; |
|
|
|
|
|
|
|
|
|
|
|
bool _isActiveSequence(int token) => !isClosed && token == _sequenceToken; |
|
|
|
|
|
|
|
|
/// ------------Functions------------ |
|
|
/// ------------Functions------------ |
|
|
// void startScrollTitle({Duration? audioDuration}) { |
|
|
// void startScrollTitle({Duration? audioDuration}) { |
|
|
// if (audioDuration == null || audioDuration == Duration.zero) return; |
|
|
// if (audioDuration == null || audioDuration == Duration.zero) return; |
|
|
@ -125,12 +131,12 @@ class QuestionBloc extends Bloc<QuestionEvent, QuestionState> { |
|
|
|
|
|
|
|
|
Future<void> playDiamondAudio() async { |
|
|
Future<void> playDiamondAudio() async { |
|
|
await _mainAudioService.setAudio(assetPath: MyAudios.diamondEnd); |
|
|
await _mainAudioService.setAudio(assetPath: MyAudios.diamondEnd); |
|
|
await _mainAudioService.play(); |
|
|
|
|
|
|
|
|
await _mainAudioService.play(waitUntilComplete: true); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
Future<void> playRightAnswerAudio() async { |
|
|
Future<void> playRightAnswerAudio() async { |
|
|
await _mainAudioService.setAudio(assetPath: MyAudios.rightAnswer); |
|
|
await _mainAudioService.setAudio(assetPath: MyAudios.rightAnswer); |
|
|
await _mainAudioService.play(); |
|
|
|
|
|
|
|
|
await _mainAudioService.play(waitUntilComplete: true); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
Future<void> initAudios() async { |
|
|
Future<void> initAudios() async { |
|
|
@ -154,17 +160,17 @@ class QuestionBloc extends Bloc<QuestionEvent, QuestionState> { |
|
|
debugPrint('playWrongAudio: $audio'); |
|
|
debugPrint('playWrongAudio: $audio'); |
|
|
|
|
|
|
|
|
await _mainAudioService.setAudio(assetPath: audio); |
|
|
await _mainAudioService.setAudio(assetPath: audio); |
|
|
await _mainAudioService.play(); |
|
|
|
|
|
|
|
|
await _mainAudioService.play(waitUntilComplete: true); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
Future<void> playAnswerAudio({String? audio}) async { |
|
|
Future<void> playAnswerAudio({String? audio}) async { |
|
|
await _mainAudioService.setAudio(filePath: audio); |
|
|
await _mainAudioService.setAudio(filePath: audio); |
|
|
await _mainAudioService.play(); |
|
|
|
|
|
|
|
|
await _mainAudioService.play(waitUntilComplete: true); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
Future<void> playQuestionAudio() async { |
|
|
Future<void> playQuestionAudio() async { |
|
|
await _mainAudioService.setAudio(filePath: state.currentQuestion?.audio); |
|
|
await _mainAudioService.setAudio(filePath: state.currentQuestion?.audio); |
|
|
await _mainAudioService.play(); |
|
|
|
|
|
|
|
|
await _mainAudioService.play(waitUntilComplete: true); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
Future<void> changeMute() async { |
|
|
Future<void> changeMute() async { |
|
|
@ -177,13 +183,17 @@ class QuestionBloc extends Bloc<QuestionEvent, QuestionState> { |
|
|
|
|
|
|
|
|
Future<void> showQueueAnswer() async { |
|
|
Future<void> showQueueAnswer() async { |
|
|
if (!showAnswerSequence) return; |
|
|
if (!showAnswerSequence) return; |
|
|
final List<AnswerEntity> answers = state.currentQuestion?.answers ?? []; |
|
|
|
|
|
|
|
|
final int token = _sequenceToken; |
|
|
|
|
|
final List<AnswerEntity> answers = List<AnswerEntity>.from( |
|
|
|
|
|
state.currentQuestion?.answers ?? const <AnswerEntity>[], |
|
|
|
|
|
); |
|
|
if (answers.isNotEmpty) { |
|
|
if (answers.isNotEmpty) { |
|
|
answers.removeWhere((e) => e.imageId == null); |
|
|
answers.removeWhere((e) => e.imageId == null); |
|
|
} |
|
|
} |
|
|
for (final answer in answers) { |
|
|
for (final answer in answers) { |
|
|
|
|
|
if (!_isActiveSequence(token)) return; |
|
|
await Future.delayed(const Duration(milliseconds: 350), () async { |
|
|
await Future.delayed(const Duration(milliseconds: 350), () async { |
|
|
if (MyContext.get.mounted) { |
|
|
|
|
|
|
|
|
if (_isActiveSequence(token) && MyContext.get.mounted) { |
|
|
await showAnswerDialog( |
|
|
await showAnswerDialog( |
|
|
context: MyContext.get, |
|
|
context: MyContext.get, |
|
|
answerEntity: answer, |
|
|
answerEntity: answer, |
|
|
@ -192,6 +202,7 @@ class QuestionBloc extends Bloc<QuestionEvent, QuestionState> { |
|
|
} |
|
|
} |
|
|
}); |
|
|
}); |
|
|
} |
|
|
} |
|
|
|
|
|
if (!_isActiveSequence(token)) return; |
|
|
changeGlobeState(key: MyAnimations.globeStateNormal); |
|
|
changeGlobeState(key: MyAnimations.globeStateNormal); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -264,10 +275,12 @@ class QuestionBloc extends Bloc<QuestionEvent, QuestionState> { |
|
|
GetLevelEvent event, |
|
|
GetLevelEvent event, |
|
|
Emitter<QuestionState> emit, |
|
|
Emitter<QuestionState> emit, |
|
|
) async { |
|
|
) async { |
|
|
|
|
|
final int token = _nextSequenceToken(); |
|
|
await _getLevelUseCase(QuestionParams(id: int.parse(event.id ?? '0'))).then( |
|
|
await _getLevelUseCase(QuestionParams(id: int.parse(event.id ?? '0'))).then( |
|
|
(value) { |
|
|
(value) { |
|
|
value.fold( |
|
|
value.fold( |
|
|
(data) async { |
|
|
(data) async { |
|
|
|
|
|
if (!_isActiveSequence(token)) return; |
|
|
final LevelEntity level = LevelEntity( |
|
|
final LevelEntity level = LevelEntity( |
|
|
id: data.id, |
|
|
id: data.id, |
|
|
order: data.order, |
|
|
order: data.order, |
|
|
@ -286,11 +299,14 @@ class QuestionBloc extends Bloc<QuestionEvent, QuestionState> { |
|
|
correctAnswer: false, |
|
|
correctAnswer: false, |
|
|
), |
|
|
), |
|
|
); |
|
|
); |
|
|
|
|
|
if (!_isActiveSequence(token)) return; |
|
|
imageAnimationController?.forward(); |
|
|
imageAnimationController?.forward(); |
|
|
changeGlobeState(key: MyAnimations.globeStateSpeaking); |
|
|
changeGlobeState(key: MyAnimations.globeStateSpeaking); |
|
|
await playQuestionAudio(); |
|
|
await playQuestionAudio(); |
|
|
|
|
|
if (!_isActiveSequence(token)) return; |
|
|
imageAnimationController?.reverse(); |
|
|
imageAnimationController?.reverse(); |
|
|
answerAnimationController?.forward().then((value) { |
|
|
answerAnimationController?.forward().then((value) { |
|
|
|
|
|
if (!_isActiveSequence(token)) return; |
|
|
showQueueAnswer(); |
|
|
showQueueAnswer(); |
|
|
}); |
|
|
}); |
|
|
}, |
|
|
}, |
|
|
@ -308,6 +324,7 @@ class QuestionBloc extends Bloc<QuestionEvent, QuestionState> { |
|
|
ChooseAnswerEvent event, |
|
|
ChooseAnswerEvent event, |
|
|
Emitter<QuestionState> emit, |
|
|
Emitter<QuestionState> emit, |
|
|
) async { |
|
|
) async { |
|
|
|
|
|
final int token = _nextSequenceToken(); |
|
|
emit(state.copyWith(correctAnswer: event.chooseCorrectAnswer)); |
|
|
emit(state.copyWith(correctAnswer: event.chooseCorrectAnswer)); |
|
|
|
|
|
|
|
|
if (event.chooseCorrectAnswer) { |
|
|
if (event.chooseCorrectAnswer) { |
|
|
@ -322,9 +339,11 @@ class QuestionBloc extends Bloc<QuestionEvent, QuestionState> { |
|
|
AnswerEntity(), |
|
|
AnswerEntity(), |
|
|
showConfetti: true, |
|
|
showConfetti: true, |
|
|
); |
|
|
); |
|
|
|
|
|
if (!_isActiveSequence(token)) return; |
|
|
scrollController.jumpTo(0); |
|
|
scrollController.jumpTo(0); |
|
|
answerAnimationController?.reverse(); |
|
|
answerAnimationController?.reverse(); |
|
|
await Future.delayed(const Duration(seconds: 1), () async { |
|
|
await Future.delayed(const Duration(seconds: 1), () async { |
|
|
|
|
|
if (!_isActiveSequence(token)) return; |
|
|
final QuestionEntity? findPreQuestion = state.currentQuestion; |
|
|
final QuestionEntity? findPreQuestion = state.currentQuestion; |
|
|
final int findIndex = (findPreQuestion?.order ?? 1); |
|
|
final int findIndex = (findPreQuestion?.order ?? 1); |
|
|
final newCurrentQuestion = state.levelEntity?.questions?[findIndex]; |
|
|
final newCurrentQuestion = state.levelEntity?.questions?[findIndex]; |
|
|
@ -335,6 +354,7 @@ class QuestionBloc extends Bloc<QuestionEvent, QuestionState> { |
|
|
await Future.delayed(const Duration(milliseconds: 400)); |
|
|
await Future.delayed(const Duration(milliseconds: 400)); |
|
|
} |
|
|
} |
|
|
emit(state.copyWith(currentQuestion: newCurrentQuestion)); |
|
|
emit(state.copyWith(currentQuestion: newCurrentQuestion)); |
|
|
|
|
|
if (!_isActiveSequence(token)) return; |
|
|
if (isLastQuestion) { |
|
|
if (isLastQuestion) { |
|
|
int currentLevel = int.parse( |
|
|
int currentLevel = int.parse( |
|
|
LocalStorage.readData(key: MyConstants.currentLevel) ?? '1', |
|
|
LocalStorage.readData(key: MyConstants.currentLevel) ?? '1', |
|
|
@ -349,12 +369,15 @@ class QuestionBloc extends Bloc<QuestionEvent, QuestionState> { |
|
|
} else { |
|
|
} else { |
|
|
showingAnswerSequence(show: true); |
|
|
showingAnswerSequence(show: true); |
|
|
await Future.delayed(const Duration(seconds: 1)); |
|
|
await Future.delayed(const Duration(seconds: 1)); |
|
|
|
|
|
if (!_isActiveSequence(token)) return; |
|
|
imageAnimationController?.forward(); |
|
|
imageAnimationController?.forward(); |
|
|
scrollController.jumpTo(0); |
|
|
scrollController.jumpTo(0); |
|
|
changeGlobeState(key: MyAnimations.globeStateSpeaking); |
|
|
changeGlobeState(key: MyAnimations.globeStateSpeaking); |
|
|
await playQuestionAudio(); |
|
|
await playQuestionAudio(); |
|
|
|
|
|
if (!_isActiveSequence(token)) return; |
|
|
imageAnimationController?.reverse(); |
|
|
imageAnimationController?.reverse(); |
|
|
answerAnimationController?.forward().then((value) { |
|
|
answerAnimationController?.forward().then((value) { |
|
|
|
|
|
if (!_isActiveSequence(token)) return; |
|
|
showQueueAnswer(); |
|
|
showQueueAnswer(); |
|
|
}); |
|
|
}); |
|
|
} |
|
|
} |
|
|
|