fix/animation #41

Merged
amirreza.chegini merged 2 commits from fix/animation into develop 1 month ago
  1. 4
      lib/core/routers/hero_dialog_route.dart
  2. 10
      lib/core/routers/my_routes.dart
  3. 3
      lib/core/services/audio_service.dart
  4. 10
      lib/core/utils/context_provider.dart
  5. 10
      lib/core/utils/my_context.dart
  6. 6
      lib/core/utils/screen_size.dart
  7. 6
      lib/features/download/presentation/bloc/download_bloc.dart
  8. 6
      lib/features/intro/presentation/bloc/intro_bloc.dart
  9. 10
      lib/features/language/presentation/bloc/language_bloc.dart
  10. 102
      lib/features/level/presentation/bloc/level_bloc.dart
  11. 93
      lib/features/question/presentation/bloc/question_bloc.dart
  12. 57
      lib/features/question/presentation/ui/screens/answer_screen.dart
  13. 2
      lib/features/question/presentation/ui/screens/question_screen.dart

4
lib/core/routers/hero_dialog_route.dart

@ -16,13 +16,13 @@ class HeroDialogRoute<T> extends PageRoute<T> {
bool get fullscreenDialog => false; bool get fullscreenDialog => false;
@override @override
bool get barrierDismissible => true;
bool get barrierDismissible => false;
@override @override
Duration get transitionDuration => const Duration(seconds: 1); // Adjust as needed Duration get transitionDuration => const Duration(seconds: 1); // Adjust as needed
@override @override
bool get maintainState => true;
bool get maintainState => false;
@override @override
Color get barrierColor => Color(0XFF322386).withValues(alpha: 0.3); // Or your desired barrier color Color get barrierColor => Color(0XFF322386).withValues(alpha: 0.3); // Or your desired barrier color

10
lib/core/routers/my_routes.dart

@ -2,7 +2,7 @@ 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/core/constants/my_constants.dart'; import 'package:hadi_hoda_flutter/core/constants/my_constants.dart';
import 'package:hadi_hoda_flutter/core/middlewares/my_middlewares.dart'; import 'package:hadi_hoda_flutter/core/middlewares/my_middlewares.dart';
import 'package:hadi_hoda_flutter/core/utils/context_provider.dart';
import 'package:hadi_hoda_flutter/core/utils/my_context.dart';
import 'package:hadi_hoda_flutter/features/download/presentation/bloc/download_bloc.dart'; import 'package:hadi_hoda_flutter/features/download/presentation/bloc/download_bloc.dart';
import 'package:hadi_hoda_flutter/features/download/presentation/bloc/download_event.dart'; import 'package:hadi_hoda_flutter/features/download/presentation/bloc/download_event.dart';
import 'package:hadi_hoda_flutter/features/download/presentation/ui/download_page.dart'; import 'package:hadi_hoda_flutter/features/download/presentation/ui/download_page.dart';
@ -40,9 +40,11 @@ class Routes {
static const String levelPage = '/level_page'; static const String levelPage = '/level_page';
} }
GoRouter get appPages => GoRouter(
final GoRouter appPages = _appPages();
GoRouter _appPages() => GoRouter(
initialLocation: Routes.splashPage, initialLocation: Routes.splashPage,
navigatorKey: ContextProvider.navigatorKey,
navigatorKey: MyContext.rootNavigatorKey,
routes: [ routes: [
GoRoute( GoRoute(
name: Routes.introPage, name: Routes.introPage,
@ -131,4 +133,4 @@ GoRouter get appPages => GoRouter(
), ),
), ),
], ],
);
);

3
lib/core/services/audio_service.dart

@ -29,6 +29,9 @@ class AudioService {
Future<void> play() async { Future<void> play() async {
try { try {
await _player.play(); await _player.play();
await _player.processingStateStream
.firstWhere((s) => s == ProcessingState.completed);
return;
} catch (e) { } catch (e) {
if (kDebugMode) { if (kDebugMode) {
print('$e'); print('$e');

10
lib/core/utils/context_provider.dart

@ -1,10 +0,0 @@
import 'package:flutter/cupertino.dart';
class ContextProvider {
static const ContextProvider _i = ContextProvider._internal();
const ContextProvider._internal();
factory ContextProvider() => _i;
static GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
static BuildContext context = navigatorKey.currentContext!;
}

10
lib/core/utils/my_context.dart

@ -0,0 +1,10 @@
import 'package:flutter/cupertino.dart';
class MyContext {
static const MyContext _i = MyContext._internal();
const MyContext._internal();
factory MyContext() => _i;
static GlobalKey<NavigatorState> rootNavigatorKey = GlobalKey<NavigatorState>();
static BuildContext get = rootNavigatorKey.currentContext!;
}

6
lib/core/utils/screen_size.dart

@ -1,5 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:hadi_hoda_flutter/core/utils/context_provider.dart';
import 'package:hadi_hoda_flutter/core/utils/my_context.dart';
extension ScreenSize on BuildContext { extension ScreenSize on BuildContext {
double get widthScreen => MediaQuery.sizeOf(this).width; double get widthScreen => MediaQuery.sizeOf(this).width;
@ -8,6 +8,6 @@ extension ScreenSize on BuildContext {
extension AdaptiveSize on double { extension AdaptiveSize on double {
double get w => ContextProvider.context.widthScreen * this;
double get h => ContextProvider.context.heightScreen * this;
double get w => MyContext.get.widthScreen * this;
double get h => MyContext.get.heightScreen * this;
} }

6
lib/features/download/presentation/bloc/download_bloc.dart

@ -6,8 +6,8 @@ import 'package:hadi_hoda_flutter/core/constants/my_constants.dart';
import 'package:hadi_hoda_flutter/core/params/no_params.dart'; import 'package:hadi_hoda_flutter/core/params/no_params.dart';
import 'package:hadi_hoda_flutter/core/routers/my_routes.dart'; import 'package:hadi_hoda_flutter/core/routers/my_routes.dart';
import 'package:hadi_hoda_flutter/core/status/base_status.dart'; import 'package:hadi_hoda_flutter/core/status/base_status.dart';
import 'package:hadi_hoda_flutter/core/utils/context_provider.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_context.dart';
import 'package:hadi_hoda_flutter/features/download/domain/entities/download_entity.dart'; import 'package:hadi_hoda_flutter/features/download/domain/entities/download_entity.dart';
import 'package:hadi_hoda_flutter/features/download/domain/usecases/get_audios_usecase.dart'; import 'package:hadi_hoda_flutter/features/download/domain/usecases/get_audios_usecase.dart';
import 'package:hadi_hoda_flutter/features/download/domain/usecases/get_images_usecase.dart'; import 'package:hadi_hoda_flutter/features/download/domain/usecases/get_images_usecase.dart';
@ -86,8 +86,8 @@ class DownloadBloc extends Bloc<DownloadEvent, DownloadState> {
value.fold( value.fold(
(data) async { (data) async {
await LocalStorage.saveData(key: MyConstants.firstDownload, value: 'true'); await LocalStorage.saveData(key: MyConstants.firstDownload, value: 'true');
if(ContextProvider.context.mounted){
ContextProvider.context.goNamed(Routes.homePage);
if(MyContext.get.mounted){
MyContext.get.goNamed(Routes.homePage);
} }
}, },
(error) { (error) {

6
lib/features/intro/presentation/bloc/intro_bloc.dart

@ -5,8 +5,8 @@ import 'package:flutter/cupertino.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.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/routers/my_routes.dart'; import 'package:hadi_hoda_flutter/core/routers/my_routes.dart';
import 'package:hadi_hoda_flutter/core/utils/context_provider.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_context.dart';
import 'package:hadi_hoda_flutter/features/intro/presentation/bloc/intro_event.dart'; import 'package:hadi_hoda_flutter/features/intro/presentation/bloc/intro_event.dart';
import 'package:hadi_hoda_flutter/features/intro/presentation/bloc/intro_state.dart'; import 'package:hadi_hoda_flutter/features/intro/presentation/bloc/intro_state.dart';
import 'package:hadi_hoda_flutter/features/intro/presentation/ui/screens/intro_1_screen.dart'; import 'package:hadi_hoda_flutter/features/intro/presentation/ui/screens/intro_1_screen.dart';
@ -37,8 +37,8 @@ class IntroBloc extends Bloc<IntroEvent, IntroState> {
/// ------------Functions------------ /// ------------Functions------------
Future<void> goToLevelPage() async { Future<void> goToLevelPage() async {
await LocalStorage.saveData(key: MyConstants.firstIntro, value: 'true'); await LocalStorage.saveData(key: MyConstants.firstIntro, value: 'true');
if (ContextProvider.context.mounted) {
ContextProvider.context.goNamed(Routes.levelPage);
if (MyContext.get.mounted) {
MyContext.get.goNamed(Routes.levelPage);
} }
} }

10
lib/features/language/presentation/bloc/language_bloc.dart

@ -6,8 +6,8 @@ import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.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/routers/my_routes.dart'; import 'package:hadi_hoda_flutter/core/routers/my_routes.dart';
import 'package:hadi_hoda_flutter/core/utils/context_provider.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_context.dart';
import 'package:hadi_hoda_flutter/core/utils/storage_path.dart'; import 'package:hadi_hoda_flutter/core/utils/storage_path.dart';
import 'package:hadi_hoda_flutter/features/app/presentation/bloc/app_bloc.dart'; import 'package:hadi_hoda_flutter/features/app/presentation/bloc/app_bloc.dart';
import 'package:hadi_hoda_flutter/features/app/presentation/bloc/app_event.dart'; import 'package:hadi_hoda_flutter/features/app/presentation/bloc/app_event.dart';
@ -60,16 +60,16 @@ class LanguageBloc extends Bloc<LanguageEvent, LanguageState> {
'${StoragePath.documentDir.path}/${state.selectedLang '${StoragePath.documentDir.path}/${state.selectedLang
.code}/question_audio') .code}/question_audio')
.existsSync()) { .existsSync()) {
if (ContextProvider.context.mounted) {
ContextProvider.context.goNamed(Routes.homePage);
if (MyContext.get.mounted) {
MyContext.get.goNamed(Routes.homePage);
} }
} else { } else {
await Future.wait([ await Future.wait([
LocalStorage.deleteData(key: MyConstants.downloadedAudio), LocalStorage.deleteData(key: MyConstants.downloadedAudio),
LocalStorage.deleteData(key: MyConstants.extractedAudio), LocalStorage.deleteData(key: MyConstants.extractedAudio),
]); ]);
if (ContextProvider.context.mounted) {
ContextProvider.context.goNamed(Routes.downloadPage);
if (MyContext.get.mounted) {
MyContext.get.goNamed(Routes.downloadPage);
} }
} }
} }

102
lib/features/level/presentation/bloc/level_bloc.dart

@ -9,8 +9,8 @@ import 'package:hadi_hoda_flutter/core/params/level_params.dart';
import 'package:hadi_hoda_flutter/core/routers/my_routes.dart'; import 'package:hadi_hoda_flutter/core/routers/my_routes.dart';
import 'package:hadi_hoda_flutter/core/services/audio_service.dart'; import 'package:hadi_hoda_flutter/core/services/audio_service.dart';
import 'package:hadi_hoda_flutter/core/status/base_status.dart'; import 'package:hadi_hoda_flutter/core/status/base_status.dart';
import 'package:hadi_hoda_flutter/core/utils/context_provider.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_context.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/utils/set_platform_size.dart';
import 'package:hadi_hoda_flutter/features/level/domain/entity/level_entity.dart'; import 'package:hadi_hoda_flutter/features/level/domain/entity/level_entity.dart';
@ -47,128 +47,128 @@ class LevelBloc extends Bloc<LevelEvent, LevelState> {
/// ------------Variables------------ /// ------------Variables------------
final List<LevelLocation> locationList = [ final List<LevelLocation> locationList = [
LevelLocation( LevelLocation(
bottom: setSize(context: ContextProvider.context, mobile: -0.03.h, tablet: -0.03.h),
left: setSize(context: ContextProvider.context, mobile: 0.1.w, tablet: 0.2.w),
bottom: setSize(context: MyContext.get, mobile: -0.03.h, tablet: -0.03.h),
left: setSize(context: MyContext.get, mobile: 0.1.w, tablet: 0.2.w),
index: 0, index: 0,
), ),
LevelLocation( LevelLocation(
bottom: setSize(context: ContextProvider.context, mobile: 0.03.h, tablet: 0.1.h),
left: setSize(context: ContextProvider.context, mobile: 0.28.w, tablet: 0.4.w),
bottom: setSize(context: MyContext.get, mobile: 0.03.h, tablet: 0.1.h),
left: setSize(context: MyContext.get, mobile: 0.28.w, tablet: 0.4.w),
index: 1, index: 1,
), ),
LevelLocation( LevelLocation(
bottom: setSize(context: ContextProvider.context, mobile: 0.1.h, tablet: 0.21.h),
left: setSize(context: ContextProvider.context, mobile: 0.14.w, tablet: 0.2.w),
bottom: setSize(context: MyContext.get, mobile: 0.1.h, tablet: 0.21.h),
left: setSize(context: MyContext.get, mobile: 0.14.w, tablet: 0.2.w),
index: 2, index: 2,
), ),
LevelLocation( LevelLocation(
bottom: setSize(context: ContextProvider.context, mobile: 0.2.h, tablet: 0.38.h),
left: setSize(context: ContextProvider.context, mobile: 0.3.w, tablet: 0.3.w),
bottom: setSize(context: MyContext.get, mobile: 0.2.h, tablet: 0.38.h),
left: setSize(context: MyContext.get, mobile: 0.3.w, tablet: 0.3.w),
index: 3, index: 3,
), ),
LevelLocation( LevelLocation(
bottom: setSize(context: ContextProvider.context, mobile: 0.24.h, tablet: 0.47.h),
left: setSize(context: ContextProvider.context, mobile: 0.5.w, tablet: 0.5.w),
bottom: setSize(context: MyContext.get, mobile: 0.24.h, tablet: 0.47.h),
left: setSize(context: MyContext.get, mobile: 0.5.w, tablet: 0.5.w),
index: 4, index: 4,
), ),
LevelLocation( LevelLocation(
bottom: setSize(context: ContextProvider.context, mobile: 0.33.h, tablet: 0.55.h),
left: setSize(context: ContextProvider.context, mobile: 0.65.w, tablet: 0.8.w),
bottom: setSize(context: MyContext.get, mobile: 0.33.h, tablet: 0.55.h),
left: setSize(context: MyContext.get, mobile: 0.65.w, tablet: 0.8.w),
index: 5, index: 5,
), ),
LevelLocation( LevelLocation(
bottom: setSize(context: ContextProvider.context, mobile: 0.45.h, tablet: 0.8.h),
left: setSize(context: ContextProvider.context, mobile: 0.57.w, tablet: 0.8.w),
bottom: setSize(context: MyContext.get, mobile: 0.45.h, tablet: 0.8.h),
left: setSize(context: MyContext.get, mobile: 0.57.w, tablet: 0.8.w),
index: 6, index: 6,
), ),
LevelLocation( LevelLocation(
bottom: setSize(context: ContextProvider.context, mobile: 0.55.h, tablet: 1.1.h),
left: setSize(context: ContextProvider.context, mobile: 0.57.w, tablet: 0.77.w),
bottom: setSize(context: MyContext.get, mobile: 0.55.h, tablet: 1.1.h),
left: setSize(context: MyContext.get, mobile: 0.57.w, tablet: 0.77.w),
index: 7, index: 7,
), ),
LevelLocation( LevelLocation(
bottom: setSize(context: ContextProvider.context, mobile: 0.6.h, tablet: 1.2.h),
left: setSize(context: ContextProvider.context, mobile: 0.4.w, tablet: 0.65.w),
bottom: setSize(context: MyContext.get, mobile: 0.6.h, tablet: 1.2.h),
left: setSize(context: MyContext.get, mobile: 0.4.w, tablet: 0.65.w),
index: 8, index: 8,
), ),
LevelLocation( LevelLocation(
bottom: setSize(context: ContextProvider.context, mobile: 0.63.h, tablet: 1.25.h),
left: setSize(context: ContextProvider.context, mobile: 0.2.w, tablet: 0.3.w),
bottom: setSize(context: MyContext.get, mobile: 0.63.h, tablet: 1.25.h),
left: setSize(context: MyContext.get, mobile: 0.2.w, tablet: 0.3.w),
index: 9, index: 9,
), ),
LevelLocation( LevelLocation(
bottom: setSize(context: ContextProvider.context, mobile: 0.7.h, tablet: 1.38.h),
left: setSize(context: ContextProvider.context, mobile: 0, tablet: 0.04.w),
bottom: setSize(context: MyContext.get, mobile: 0.7.h, tablet: 1.38.h),
left: setSize(context: MyContext.get, mobile: 0, tablet: 0.04.w),
index: 10, index: 10,
), ),
LevelLocation( LevelLocation(
bottom: setSize(context: ContextProvider.context, mobile: 0.75.h, tablet: 1.46.h),
left: setSize(context: ContextProvider.context, mobile: 0.15.w, tablet: 0.22.w),
bottom: setSize(context: MyContext.get, mobile: 0.75.h, tablet: 1.46.h),
left: setSize(context: MyContext.get, mobile: 0.15.w, tablet: 0.22.w),
index: 11, index: 11,
), ),
LevelLocation( LevelLocation(
bottom: setSize(context: ContextProvider.context, mobile: 0.78.h, tablet: 1.52.h),
left: setSize(context: ContextProvider.context, mobile: 0.4.w, tablet: 0.45.w),
bottom: setSize(context: MyContext.get, mobile: 0.78.h, tablet: 1.52.h),
left: setSize(context: MyContext.get, mobile: 0.4.w, tablet: 0.45.w),
index: 12, index: 12,
), ),
LevelLocation( LevelLocation(
bottom: setSize(context: ContextProvider.context, mobile: 0.85.h, tablet: 1.68.h),
left: setSize(context: ContextProvider.context, mobile: 0.5.w, tablet: 0.68.w),
bottom: setSize(context: MyContext.get, mobile: 0.85.h, tablet: 1.68.h),
left: setSize(context: MyContext.get, mobile: 0.5.w, tablet: 0.68.w),
index: 13, index: 13,
), ),
LevelLocation( LevelLocation(
bottom: setSize(context: ContextProvider.context, mobile: 0.94.h, tablet: 1.8.h),
left: setSize(context: ContextProvider.context, mobile: 0.45.w, tablet: 0.6.w),
bottom: setSize(context: MyContext.get, mobile: 0.94.h, tablet: 1.8.h),
left: setSize(context: MyContext.get, mobile: 0.45.w, tablet: 0.6.w),
index: 14, index: 14,
), ),
LevelLocation( LevelLocation(
bottom: setSize(context: ContextProvider.context, mobile: 1.02.h, tablet: 1.95.h),
left: setSize(context: ContextProvider.context, mobile: 0.45.w, tablet: 0.6.w),
bottom: setSize(context: MyContext.get, mobile: 1.02.h, tablet: 1.95.h),
left: setSize(context: MyContext.get, mobile: 0.45.w, tablet: 0.6.w),
index: 15, index: 15,
), ),
LevelLocation( LevelLocation(
bottom: setSize(context: ContextProvider.context, mobile: 1.02.h, tablet: 2.01.h),
left: setSize(context: ContextProvider.context, mobile: 0.2.w, tablet: 0.4.w),
bottom: setSize(context: MyContext.get, mobile: 1.02.h, tablet: 2.01.h),
left: setSize(context: MyContext.get, mobile: 0.2.w, tablet: 0.4.w),
index: 16, index: 16,
), ),
LevelLocation( LevelLocation(
bottom: setSize(context: ContextProvider.context, mobile: 1.02.h, tablet: 2.0.h),
left: setSize(context: ContextProvider.context, mobile: 0, tablet: 0.1.w),
bottom: setSize(context: MyContext.get, mobile: 1.02.h, tablet: 2.0.h),
left: setSize(context: MyContext.get, mobile: 0, tablet: 0.1.w),
index: 17, index: 17,
), ),
LevelLocation( LevelLocation(
bottom: setSize(context: ContextProvider.context, mobile: 1.1.h, tablet: 2.17.h),
left: setSize(context: ContextProvider.context, mobile: 0, tablet: 0.04.w),
bottom: setSize(context: MyContext.get, mobile: 1.1.h, tablet: 2.17.h),
left: setSize(context: MyContext.get, mobile: 0, tablet: 0.04.w),
index: 18, index: 18,
), ),
LevelLocation( LevelLocation(
bottom: setSize(context: ContextProvider.context, mobile: 1.2.h, tablet: 2.32.h),
left: setSize(context: ContextProvider.context, mobile: 0.05.w, tablet: 0.1.w),
bottom: setSize(context: MyContext.get, mobile: 1.2.h, tablet: 2.32.h),
left: setSize(context: MyContext.get, mobile: 0.05.w, tablet: 0.1.w),
index: 19, index: 19,
), ),
LevelLocation( LevelLocation(
bottom: setSize(context: ContextProvider.context, mobile: 1.23.h, tablet: 2.35.h),
left: setSize(context: ContextProvider.context, mobile: 0.23.w, tablet: 0.25.w),
bottom: setSize(context: MyContext.get, mobile: 1.23.h, tablet: 2.35.h),
left: setSize(context: MyContext.get, mobile: 0.23.w, tablet: 0.25.w),
index: 20, index: 20,
), ),
LevelLocation( LevelLocation(
bottom: setSize(context: ContextProvider.context, mobile: 1.31.h, tablet: 2.5.h),
left: setSize(context: ContextProvider.context, mobile: 0.2.w, tablet: 0.33.w),
bottom: setSize(context: MyContext.get, mobile: 1.31.h, tablet: 2.5.h),
left: setSize(context: MyContext.get, mobile: 0.2.w, tablet: 0.33.w),
index: 21, index: 21,
), ),
LevelLocation( LevelLocation(
bottom: setSize(context: ContextProvider.context, mobile: 1.37.h, tablet: 2.6.h),
left: setSize(context: ContextProvider.context, mobile: 0.1.w, tablet: 0.2.w),
bottom: setSize(context: MyContext.get, mobile: 1.37.h, tablet: 2.6.h),
left: setSize(context: MyContext.get, mobile: 0.1.w, tablet: 0.2.w),
index: 22, index: 22,
), ),
LevelLocation( LevelLocation(
bottom: setSize(context: ContextProvider.context, mobile: 1.45.h, tablet: 2.7.h),
left: setSize(context: ContextProvider.context, mobile: 0.1.w, tablet: 0.1.w),
bottom: setSize(context: MyContext.get, mobile: 1.45.h, tablet: 2.7.h),
left: setSize(context: MyContext.get, mobile: 0.1.w, tablet: 0.1.w),
index: 23, index: 23,
), ),
LevelLocation( LevelLocation(
bottom: setSize(context: ContextProvider.context, mobile: 1.5.h, tablet: 2.8.h),
left: setSize(context: ContextProvider.context, mobile: 0.2.w, tablet: 0.15.w),
bottom: setSize(context: MyContext.get, mobile: 1.5.h, tablet: 2.8.h),
left: setSize(context: MyContext.get, mobile: 0.2.w, tablet: 0.15.w),
index: 24, index: 24,
), ),
]; ];

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

@ -10,8 +10,8 @@ import 'package:hadi_hoda_flutter/core/routers/hero_dialog_route.dart';
import 'package:hadi_hoda_flutter/core/routers/my_routes.dart'; import 'package:hadi_hoda_flutter/core/routers/my_routes.dart';
import 'package:hadi_hoda_flutter/core/services/audio_service.dart'; import 'package:hadi_hoda_flutter/core/services/audio_service.dart';
import 'package:hadi_hoda_flutter/core/status/base_status.dart'; import 'package:hadi_hoda_flutter/core/status/base_status.dart';
import 'package:hadi_hoda_flutter/core/utils/context_provider.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_context.dart';
import 'package:hadi_hoda_flutter/core/widgets/dialog/hadith_dialog.dart'; import 'package:hadi_hoda_flutter/core/widgets/dialog/hadith_dialog.dart';
import 'package:hadi_hoda_flutter/features/level/domain/entity/level_entity.dart'; import 'package:hadi_hoda_flutter/features/level/domain/entity/level_entity.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';
@ -40,7 +40,7 @@ class QuestionBloc extends Bloc<QuestionEvent, QuestionState> {
@override @override
Future<void> close() { Future<void> close() {
ShowcaseView.get().unregister();
unRegisterShowCase();
return super.close(); return super.close();
} }
@ -63,7 +63,6 @@ class QuestionBloc extends Bloc<QuestionEvent, QuestionState> {
'guide_key': GlobalKey(), 'guide_key': GlobalKey(),
}; };
late final Stream<double> volumeStream; late final Stream<double> volumeStream;
bool isPlaying = false;
/// ------------Controllers------------ /// ------------Controllers------------
final AudioService _mainAudioService; final AudioService _mainAudioService;
@ -71,27 +70,37 @@ class QuestionBloc extends Bloc<QuestionEvent, QuestionState> {
/// ------------Functions------------ /// ------------Functions------------
void registerShowCase() { 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() { void startShowcase() {
if (LocalStorage.readData(key: MyConstants.firstShowcase) != 'true') { 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}) { void showHadith({required BuildContext context}) {
if(isPlaying) return;
showHadithDialog( showHadithDialog(
context: context, context: context,
hadith: state.levelEntity?.hadith ?? [], hadith: state.levelEntity?.hadith ?? [],
@ -112,8 +121,10 @@ class QuestionBloc extends Bloc<QuestionEvent, QuestionState> {
} }
Future<void> stopMusic() async { Future<void> stopMusic() async {
await _mainAudioService.stop();
await _mainAudioService.setLoopMode(isLoop: false);
await Future.wait([
_mainAudioService.stop(),
_mainAudioService.setLoopMode(isLoop: false),
]);
} }
Future<void> playCorrectAudio() async { Future<void> playCorrectAudio() async {
@ -134,6 +145,7 @@ class QuestionBloc extends Bloc<QuestionEvent, QuestionState> {
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();
await showQueueAnswer();
} }
Future<void> changeMute() async { Future<void> changeMute() async {
@ -143,21 +155,41 @@ class QuestionBloc extends Bloc<QuestionEvent, QuestionState> {
]); ]);
} }
Future<void> showQueueAnswer() async {
final List<AnswerEntity> 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<void> showAnswerDialog({ Future<void> showAnswerDialog({
required BuildContext context, required BuildContext context,
required AnswerEntity answerEntity, required AnswerEntity answerEntity,
bool showConfetti = false,
bool autoClose = false,
}) async { }) async {
Navigator.of(context).push(
await Navigator.of(context).push(
HeroDialogRoute( HeroDialogRoute(
builder: (dialogContext) { builder: (dialogContext) {
return AnswerScreen( return AnswerScreen(
answerEntity: answerEntity, answerEntity: answerEntity,
onNotifTap: (answer) => playAnswerAudio(audio: answer.audio),
showConfetti: showConfetti,
autoClose: autoClose,
); );
}, },
), ),
); );
playAnswerAudio(audio: answerEntity.audio);
} }
Future<void> getNextLevelEvent({required BuildContext context}) async { Future<void> getNextLevelEvent({required BuildContext context}) async {
@ -169,7 +201,7 @@ class QuestionBloc extends Bloc<QuestionEvent, QuestionState> {
); );
}, },
(error) { (error) {
goToLevelPage(context: ContextProvider.context);
goToLevelPage(context: MyContext.get);
}, },
), ),
); );
@ -213,16 +245,11 @@ class QuestionBloc extends Bloc<QuestionEvent, QuestionState> {
if (event.chooseCorrectAnswer) { if (event.chooseCorrectAnswer) {
playCorrectAudio(); playCorrectAudio();
await Navigator.of(ContextProvider.context).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 { await Future.delayed(Duration(seconds: 1), () async {
final QuestionEntity? findPreQuestion = state.currentQuestion; final QuestionEntity? findPreQuestion = state.currentQuestion;
@ -245,7 +272,7 @@ class QuestionBloc extends Bloc<QuestionEvent, QuestionState> {
); );
} }
} else { } else {
playQuestionAudio();
await playQuestionAudio();
} }
}); });
} else { } else {

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

@ -1,50 +1,74 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.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_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_spaces.dart';
import 'package:hadi_hoda_flutter/core/utils/context_provider.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/screen_size.dart';
import 'package:hadi_hoda_flutter/core/utils/set_platform_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/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/features/question/domain/entity/answer_entity.dart';
import 'package:hadi_hoda_flutter/init_bindings.dart';
import 'package:lottie/lottie.dart'; import 'package:lottie/lottie.dart';
class AnswerScreen extends StatefulWidget { class AnswerScreen extends StatefulWidget {
const AnswerScreen({ const AnswerScreen({
super.key, super.key,
required this.answerEntity, required this.answerEntity,
this.onNotifTap,
this.showConfetti = false,
required this.showConfetti,
required this.autoClose,
}); });
final AnswerEntity answerEntity; final AnswerEntity answerEntity;
final Function(AnswerEntity answer)? onNotifTap;
final bool showConfetti; final bool showConfetti;
final bool autoClose;
@override @override
State<AnswerScreen> createState() => _AnswerScreenState(); State<AnswerScreen> createState() => _AnswerScreenState();
} }
class _AnswerScreenState extends State<AnswerScreen> { class _AnswerScreenState extends State<AnswerScreen> {
final AudioService audioService = locator(
instanceName: MyConstants.mainAudioService,
);
@override @override
void initState() { void initState() {
super.initState(); super.initState();
back();
initWidget();
} }
Future<void> back() async {
Future<void> initWidget() async {
if (widget.showConfetti) { if (widget.showConfetti) {
await Future.delayed(Duration(seconds: 3), () { await Future.delayed(Duration(seconds: 3), () {
if (ContextProvider.context.mounted) {
ContextProvider.context.pop();
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<void> playAudio() async {
await audioService.setAudio(filePath: widget.answerEntity.audio);
await audioService.play();
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Stack( return Stack(
alignment: Alignment.center,
children: [ children: [
Center( Center(
child: Padding( child: Padding(
@ -56,7 +80,22 @@ class _AnswerScreenState extends State<AnswerScreen> {
child: AnswerBoxShow( child: AnswerBoxShow(
answer: widget.answerEntity, answer: widget.answerEntity,
index: widget.answerEntity.order ?? 0, index: widget.answerEntity.order ?? 0,
onNotifTap: widget.onNotifTap,
onNotifTap: (answer) => playAudio(),
),
),
),
Positioned(
bottom: setPlatform<double>(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
), ),
), ),
), ),

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

@ -135,7 +135,7 @@ class QuestionScreen extends StatelessWidget {
child: SizedBox( child: SizedBox(
width: context.widthScreen, width: context.widthScreen,
child: Stack( child: Stack(
alignment: Alignment.center,
alignment: AlignmentDirectional.centerStart,
children: [ children: [
MyShowcaseWidget( MyShowcaseWidget(
globalKey: context.read<QuestionBloc>().showCaseKey['guide_key']!, globalKey: context.read<QuestionBloc>().showCaseKey['guide_key']!,

Loading…
Cancel
Save