Browse Source

optimization

develop
sina 2 weeks ago
parent
commit
8f08d8ded0
  1. 10
      lib/core/services/audio_service.dart
  2. 63
      lib/features/question/presentation/bloc/question_bloc.dart
  3. 4
      lib/features/question/presentation/ui/screens/answer_screen.dart

10
lib/core/services/audio_service.dart

@ -30,12 +30,13 @@ class AudioService {
}
}
Future<void> play() async {
Future<void> play({bool waitUntilComplete = false}) async {
try {
await _player.play();
await _player.processingStateStream
.firstWhere((s) => s == ProcessingState.completed);
return;
if (!waitUntilComplete) return;
await _player.processingStateStream.firstWhere(
(s) => s == ProcessingState.completed,
);
} catch (e) {
if (kDebugMode) {
print('$e');
@ -65,6 +66,7 @@ class AudioService {
Future<void> dispose() async {
try {
await _streamController.close();
await _player.dispose();
} catch (e) {
if (kDebugMode) {

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

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

4
lib/features/question/presentation/ui/screens/answer_screen.dart

@ -63,12 +63,12 @@ class _AnswerScreenState extends State<AnswerScreen> {
Future<void> playCorrectAudio() async {
await audioService.setAudio(filePath: widget.correctAudio);
await audioService.play();
await audioService.play(waitUntilComplete: true);
}
Future<void> playAudio() async {
await audioService.setAudio(filePath: widget.answerEntity.audio);
await audioService.play();
await audioService.play(waitUntilComplete: true);
}
@override

Loading…
Cancel
Save