change somethings #64

Merged
amirreza.chegini merged 1 commits from fix/bugs into develop 8 hours ago
  1. 82
      lib/core/routers/my_routes.dart
  2. 4
      lib/core/widgets/answer_box/styles/picture_box.dart
  3. 24
      lib/core/widgets/dialog/exit_dialog.dart
  4. 8
      lib/core/widgets/dialog/reward_dialog.dart
  5. 17
      lib/core/widgets/page_transition/my_page_transition.dart
  6. 10
      lib/core/widgets/pop_scope/my_pop_scope.dart
  7. 4
      lib/features/home/presentation/ui/home_page.dart
  8. 2
      lib/features/question/presentation/bloc/question_bloc.dart
  9. 2
      lib/features/question/presentation/ui/question_page.dart
  10. 142
      lib/features/question/presentation/ui/screens/question_screen.dart

82
lib/core/routers/my_routes.dart

@ -3,6 +3,7 @@ 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/my_context.dart'; import 'package:hadi_hoda_flutter/core/utils/my_context.dart';
import 'package:hadi_hoda_flutter/core/widgets/page_transition/my_page_transition.dart';
import 'package:hadi_hoda_flutter/core/widgets/video/my_video_player.dart'; import 'package:hadi_hoda_flutter/core/widgets/video/my_video_player.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';
@ -52,15 +53,6 @@ GoRouter _appPages() => GoRouter(
initialLocation: Routes.splashPage, initialLocation: Routes.splashPage,
navigatorKey: MyContext.rootNavigatorKey, navigatorKey: MyContext.rootNavigatorKey,
routes: [ routes: [
GoRoute(
name: Routes.introPage,
path: Routes.introPage,
redirect: MyMiddlewares.intro,
builder: (context, state) => BlocProvider(
create: (context) => IntroBloc(),
child: const IntroPage(),
),
),
GoRoute( GoRoute(
name: Routes.samplePage, name: Routes.samplePage,
path: Routes.samplePage, path: Routes.samplePage,
@ -81,42 +73,60 @@ GoRouter _appPages() => GoRouter(
GoRoute( GoRoute(
name: Routes.downloadPage, name: Routes.downloadPage,
path: Routes.downloadPage, path: Routes.downloadPage,
builder: (context, state) => BlocProvider(
create: (context) => DownloadBloc(
locator(),
locator(),
locator(),
locator(),
)..add(GetImagesEvent()),
pageBuilder: (context, state) => myPageTransition(
key: state.pageKey,
child: BlocProvider(
create: (context) =>
DownloadBloc(locator(), locator(), locator(), locator())
..add(GetImagesEvent()),
child: const DownloadPage(), child: const DownloadPage(),
), ),
), ),
),
GoRoute(
name: Routes.introPage,
path: Routes.introPage,
redirect: MyMiddlewares.intro,
pageBuilder: (context, state) => myPageTransition(
key: state.pageKey,
child: BlocProvider(
create: (context) => IntroBloc(),
child: const IntroPage(),
),
),
),
GoRoute( GoRoute(
name: Routes.languagePage, name: Routes.languagePage,
path: Routes.languagePage, path: Routes.languagePage,
builder: (context, state) => BlocProvider(
pageBuilder: (context, state) => myPageTransition(
key: state.pageKey,
child: BlocProvider(
create: (context) => LanguageBloc()..add(const InitLanguageEvent()), create: (context) => LanguageBloc()..add(const InitLanguageEvent()),
child: const LanguagePage(), child: const LanguagePage(),
), ),
), ),
),
GoRoute( GoRoute(
name: Routes.homePage, name: Routes.homePage,
path: Routes.homePage, path: Routes.homePage,
builder: (context, state) => BlocProvider(
create: (context) =>
HomeBloc(
pageBuilder: (context, state) => myPageTransition(
key: state.pageKey,
child: BlocProvider(
create: (context) => HomeBloc(
locator(instanceName: MyConstants.mainAudioService), locator(instanceName: MyConstants.mainAudioService),
locator(instanceName: MyConstants.effectAudioService), locator(instanceName: MyConstants.effectAudioService),
), ),
child: const HomePage(), child: const HomePage(),
), ),
), ),
),
GoRoute( GoRoute(
name: Routes.levelPage, name: Routes.levelPage,
path: Routes.levelPage, path: Routes.levelPage,
builder: (context, state) => BlocProvider(
create: (context) =>
LevelBloc(
pageBuilder: (context, state) => myPageTransition(
key: state.pageKey,
child: BlocProvider(
create: (context) => LevelBloc(
locator(), locator(),
locator(instanceName: MyConstants.mainAudioService), locator(instanceName: MyConstants.mainAudioService),
locator(instanceName: MyConstants.effectAudioService), locator(instanceName: MyConstants.effectAudioService),
@ -124,23 +134,28 @@ GoRouter _appPages() => GoRouter(
child: const LevelPage(), child: const LevelPage(),
), ),
), ),
),
GoRoute( GoRoute(
name: Routes.guiderPage, name: Routes.guiderPage,
path: '${Routes.guiderPage}/:id', path: '${Routes.guiderPage}/:id',
builder: (context, state) => BlocProvider(
create: (context) => GuiderBloc(locator())..add(GetFirstLevelEvent(
id: state.pathParameters['id'],
)),
pageBuilder: (context, state) => myPageTransition(
key: state.pageKey,
child: BlocProvider(
create: (context) =>
GuiderBloc(locator())
..add(GetFirstLevelEvent(id: state.pathParameters['id'])),
child: const GuiderPage(), child: const GuiderPage(),
), ),
), ),
),
GoRoute( GoRoute(
name: Routes.questionPage, name: Routes.questionPage,
path: '${Routes.questionPage}/:id', path: '${Routes.questionPage}/:id',
redirect: MyMiddlewares.question, redirect: MyMiddlewares.question,
builder: (context, state) => BlocProvider(
create: (context) =>
QuestionBloc(
pageBuilder: (context, state) => myPageTransition(
key: state.pageKey,
child: BlocProvider(
create: (context) => QuestionBloc(
locator(), locator(),
locator(), locator(),
locator(instanceName: MyConstants.mainAudioService), locator(instanceName: MyConstants.mainAudioService),
@ -149,11 +164,14 @@ GoRouter _appPages() => GoRouter(
child: const QuestionPage(), child: const QuestionPage(),
), ),
), ),
),
GoRoute( GoRoute(
name: Routes.videoPage, name: Routes.videoPage,
path: Routes.videoPage, path: Routes.videoPage,
builder: (context, state) =>
MyVideoPlayer(videoURL: state.extra as String),
pageBuilder: (context, state) => myPageTransition(
key: state.pageKey,
child: MyVideoPlayer(videoURL: state.extra as String),
),
), ),
], ],
); );

4
lib/core/widgets/answer_box/styles/picture_box.dart

@ -52,7 +52,7 @@ class AnswerPictureBox extends StatelessWidget {
width: context.widthScreen, width: context.widthScreen,
height: context.heightScreen, height: context.heightScreen,
image: FileImage(File(image)), image: FileImage(File(image)),
fps: 15,
fps: 20,
autostart: autostart, autostart: autostart,
fit: BoxFit.cover, fit: BoxFit.cover,
color: MyColors.black, color: MyColors.black,
@ -63,7 +63,7 @@ class AnswerPictureBox extends StatelessWidget {
width: context.widthScreen, width: context.widthScreen,
height: context.heightScreen, height: context.heightScreen,
image: FileImage(File(image)), image: FileImage(File(image)),
fps: 15,
fps: 20,
autostart: autostart, autostart: autostart,
fit: BoxFit.cover, fit: BoxFit.cover,
), ),

24
lib/core/widgets/dialog/exit_dialog.dart

@ -12,19 +12,24 @@ import 'package:hadi_hoda_flutter/core/utils/set_platform_size.dart';
import 'package:hadi_hoda_flutter/core/widgets/dialog/styles/dialog_background.dart'; import 'package:hadi_hoda_flutter/core/widgets/dialog/styles/dialog_background.dart';
import 'package:hadi_hoda_flutter/core/widgets/dialog/styles/dialog_button.dart'; import 'package:hadi_hoda_flutter/core/widgets/dialog/styles/dialog_button.dart';
Future<void> showExitDialog({required BuildContext context, bool? backHome}) async {
Future<void> showExitDialog({
required BuildContext context,
bool? backHome,
bool? backLevel,
}) async {
await showDialog( await showDialog(
context: context, context: context,
builder: (context) => ExitDialog(backHome: backHome),
builder: (context) => ExitDialog(backHome: backHome, backLevel: backLevel),
barrierColor: MyColors.purple.withValues(alpha: 0.82), barrierColor: MyColors.purple.withValues(alpha: 0.82),
useSafeArea: false, useSafeArea: false,
); );
} }
class ExitDialog extends StatelessWidget { class ExitDialog extends StatelessWidget {
const ExitDialog({super.key, this.backHome});
const ExitDialog({super.key, this.backHome, this.backLevel});
final bool? backHome; final bool? backHome;
final bool? backLevel;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -35,7 +40,8 @@ class ExitDialog extends StatelessWidget {
child: Center( child: Center(
child: Padding( child: Padding(
padding: EdgeInsets.symmetric( padding: EdgeInsets.symmetric(
horizontal: setSize(context: context, mobile: 18, tablet: 160) ?? 0,
horizontal:
setSize(context: context, mobile: 18, tablet: 160) ?? 0,
), ),
child: DialogBackground( child: DialogBackground(
height: 260, height: 260,
@ -44,11 +50,15 @@ class ExitDialog extends StatelessWidget {
children: [ children: [
Text( Text(
context.translate.want_to_exit, context.translate.want_to_exit,
style: MYTextStyle.titr0.copyWith(color: const Color(0XFF322386)),
style: MYTextStyle.titr0.copyWith(
color: const Color(0XFF322386),
),
), ),
Text( Text(
context.translate.exit_dialog_desc, context.translate.exit_dialog_desc,
style: MYTextStyle.titr3.copyWith(color: const Color(0XFF6272A9)),
style: MYTextStyle.titr3.copyWith(
color: const Color(0XFF6272A9),
),
textAlign: TextAlign.center, textAlign: TextAlign.center,
), ),
Row( Row(
@ -79,6 +89,8 @@ class ExitDialog extends StatelessWidget {
onTap: () { onTap: () {
if (backHome ?? false) { if (backHome ?? false) {
context.goNamed(Routes.homePage); context.goNamed(Routes.homePage);
} else if (backLevel ?? false) {
context.goNamed(Routes.levelPage);
} else { } else {
SystemNavigator.pop(); SystemNavigator.pop();
} }

8
lib/core/widgets/dialog/reward_dialog.dart

@ -89,9 +89,15 @@ class RewardDialog extends StatelessWidget {
children: [ children: [
Image.network( Image.network(
prize.imageURL ?? '', prize.imageURL ?? '',
loadingBuilder: (context, child, loadingProgress) => SizedBox(
errorBuilder: (context, error, stackTrace) => Container(
height: 300, height: 300,
width: 300, width: 300,
color: const Color(0XFFE0E0E0),
),
loadingBuilder: (context, child, loadingProgress) => Container(
height: 300,
width: 300,
color: const Color(0XFFE0E0E0),
child: child, child: child,
), ),
fit: BoxFit.cover, fit: BoxFit.cover,

17
lib/core/widgets/page_transition/my_page_transition.dart

@ -0,0 +1,17 @@
import 'package:flutter/cupertino.dart';
import 'package:go_router/go_router.dart';
CustomTransitionPage<dynamic> myPageTransition({
required Widget child,
required LocalKey key,
}) {
return CustomTransitionPage(
key: key,
child: child,
transitionsBuilder: (context, animation, secondaryAnimation, child) =>
FadeTransition(
opacity: animation,
child: child,
),
);
}

10
lib/core/widgets/pop_scope/my_pop_scope.dart

@ -2,17 +2,23 @@ import 'package:flutter/material.dart';
import 'package:hadi_hoda_flutter/core/widgets/dialog/exit_dialog.dart'; import 'package:hadi_hoda_flutter/core/widgets/dialog/exit_dialog.dart';
class MyPopScope extends StatelessWidget { class MyPopScope extends StatelessWidget {
const MyPopScope({super.key, required this.child, this.backHome});
const MyPopScope({
super.key,
required this.child,
this.backHome,
this.backLevel,
});
final Widget child; final Widget child;
final bool? backHome; final bool? backHome;
final bool? backLevel;
void onPopInvokedWithResult( void onPopInvokedWithResult(
bool didPop, bool didPop,
dynamic result, dynamic result,
BuildContext context, BuildContext context,
) { ) {
showExitDialog(context: context, backHome: backHome);
showExitDialog(context: context, backHome: backHome, backLevel: backLevel);
} }
@override @override

4
lib/features/home/presentation/ui/home_page.dart

@ -47,7 +47,7 @@ class HomePage extends StatelessWidget {
top: setPlatform(android: MySpaces.s36, iOS: 50), top: setPlatform(android: MySpaces.s36, iOS: 50),
end: MySpaces.s16, end: MySpaces.s16,
child: SlideDownFade( child: SlideDownFade(
delay: const Duration(milliseconds: 200),
delay: const Duration(milliseconds: 100),
child: StreamBuilder<double>( child: StreamBuilder<double>(
initialData: 1, initialData: 1,
stream: context.read<HomeBloc>().volumeStream, stream: context.read<HomeBloc>().volumeStream,
@ -91,7 +91,7 @@ class HomePage extends StatelessWidget {
right: MySpaces.s16, right: MySpaces.s16,
child: SafeArea( child: SafeArea(
child: SlideUpFade( child: SlideUpFade(
delay: const Duration(milliseconds: 200),
delay: const Duration(milliseconds: 100),
child: Row( child: Row(
crossAxisAlignment: CrossAxisAlignment.end, crossAxisAlignment: CrossAxisAlignment.end,
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,

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

@ -170,7 +170,7 @@ class QuestionBloc extends Bloc<QuestionEvent, QuestionState> {
required AnswerEntity answerEntity, required AnswerEntity answerEntity,
String? correctAudio, String? correctAudio,
bool showConfetti = false, bool showConfetti = false,
bool autoClose = false,
bool autoClose = true,
}) async { }) async {
await Navigator.of(context).push( await Navigator.of(context).push(
HeroDialogRoute( HeroDialogRoute(

2
lib/features/question/presentation/ui/question_page.dart

@ -22,7 +22,7 @@ class QuestionPage extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
body: MyPopScope( body: MyPopScope(
backHome: true,
backLevel: true,
child: Directionality( child: Directionality(
textDirection: TextDirection.ltr, textDirection: TextDirection.ltr,
child: Container( child: Container(

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

@ -39,7 +39,9 @@ class _QuestionScreenState extends State<QuestionScreen>
void initState() { void initState() {
super.initState(); super.initState();
WidgetsBinding.instance.addObserver(this); WidgetsBinding.instance.addObserver(this);
context.read<QuestionBloc>().answerAnimationController = AnimationController(
context
.read<QuestionBloc>()
.answerAnimationController = AnimationController(
vsync: this, vsync: this,
duration: const Duration(milliseconds: 500), duration: const Duration(milliseconds: 500),
reverseDuration: const Duration(milliseconds: 500), reverseDuration: const Duration(milliseconds: 500),
@ -78,12 +80,7 @@ class _QuestionScreenState extends State<QuestionScreen>
children: [ children: [
_stepper(), _stepper(),
Expanded( Expanded(
child: Stack(
children: [
_questionImage(context),
_answers(context),
],
),
child: Stack(children: [_questionImage(context), _answers(context)]),
), ),
_bottom(context), _bottom(context),
], ],
@ -166,9 +163,10 @@ class _QuestionScreenState extends State<QuestionScreen>
children: [ children: [
Row( Row(
key: Key('${state.currentQuestion?.id}answer0'), key: Key('${state.currentQuestion?.id}answer0'),
mainAxisAlignment: MainAxisAlignment.spaceBetween,
spacing: 20,
children: [ children: [
Builder(
Expanded(
child: Builder(
key: Key('${state.currentQuestion?.id}0'), key: Key('${state.currentQuestion?.id}0'),
builder: (context) { builder: (context) {
if (state.currentQuestion?.answers?[0].imageId == if (state.currentQuestion?.answers?[0].imageId ==
@ -185,7 +183,10 @@ class _QuestionScreenState extends State<QuestionScreen>
index: 0, index: 0,
child: AnswerBox( child: AnswerBox(
index: index:
state.currentQuestion?.answers?[0].order ??
state
.currentQuestion
?.answers?[0]
.order ??
1, 1,
answer: answer:
state.currentQuestion?.answers?[0] ?? state.currentQuestion?.answers?[0] ??
@ -193,7 +194,9 @@ class _QuestionScreenState extends State<QuestionScreen>
correctAnswer: correctAnswer:
state.currentQuestion?.correctAnswer ?? 0, state.currentQuestion?.correctAnswer ?? 0,
onNotifTap: (AnswerEntity answer) { onNotifTap: (AnswerEntity answer) {
context.read<QuestionBloc>().showAnswerDialog(
context
.read<QuestionBloc>()
.showAnswerDialog(
context: context, context: context,
answerEntity: answer, answerEntity: answer,
); );
@ -212,7 +215,9 @@ class _QuestionScreenState extends State<QuestionScreen>
} }
}, },
), ),
Builder(
),
Expanded(
child: Builder(
key: Key('${state.currentQuestion?.id}1'), key: Key('${state.currentQuestion?.id}1'),
builder: (context) { builder: (context) {
if (state.currentQuestion?.answers?[1].imageId == if (state.currentQuestion?.answers?[1].imageId ==
@ -229,7 +234,10 @@ class _QuestionScreenState extends State<QuestionScreen>
index: 1, index: 1,
child: AnswerBox( child: AnswerBox(
index: index:
state.currentQuestion?.answers?[1].order ??
state
.currentQuestion
?.answers?[1]
.order ??
1, 1,
answer: answer:
state.currentQuestion?.answers?[1] ?? state.currentQuestion?.answers?[1] ??
@ -237,7 +245,9 @@ class _QuestionScreenState extends State<QuestionScreen>
correctAnswer: correctAnswer:
state.currentQuestion?.correctAnswer ?? 0, state.currentQuestion?.correctAnswer ?? 0,
onNotifTap: (AnswerEntity answer) { onNotifTap: (AnswerEntity answer) {
context.read<QuestionBloc>().showAnswerDialog(
context
.read<QuestionBloc>()
.showAnswerDialog(
context: context, context: context,
answerEntity: answer, answerEntity: answer,
); );
@ -256,16 +266,14 @@ class _QuestionScreenState extends State<QuestionScreen>
} }
}, },
), ),
),
], ],
), ),
if ((state.currentQuestion?.answers?.length ?? 0) == 3)
Row( Row(
key: Key('${state.currentQuestion?.id}answer1'), key: Key('${state.currentQuestion?.id}answer1'),
mainAxisAlignment:
(state.currentQuestion?.answers?.length ?? 0) > 3
? MainAxisAlignment.spaceBetween
: MainAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
if ((state.currentQuestion?.answers?.length ?? 0) > 2)
Builder( Builder(
key: Key('${state.currentQuestion?.id}2'), key: Key('${state.currentQuestion?.id}2'),
builder: (context) { builder: (context) {
@ -315,9 +323,68 @@ class _QuestionScreenState extends State<QuestionScreen>
} }
}, },
), ),
if ((state.currentQuestion?.answers?.length ?? 0) > 3)
Builder(
key: Key('${state.currentQuestion?.id}1'),
],
),
if ((state.currentQuestion?.answers?.length ?? 0) == 4)
Row(
key: Key('${state.currentQuestion?.id}answer2'),
spacing: 20,
children: [
Expanded(
child: Builder(
key: Key('${state.currentQuestion?.id}2'),
builder: (context) {
if (state.currentQuestion?.answers?[2].imageId ==
null) {
return const SizedBox.shrink();
} else {
return SizedBox(
width: 180,
height: 250,
child: SlideAnim(
controller: context
.read<QuestionBloc>()
.answerAnimationController!,
index: 2,
child: AnswerBox(
index:
state
.currentQuestion
?.answers?[2]
.order ??
1,
answer:
state.currentQuestion?.answers?[2] ??
AnswerEntity(),
correctAnswer:
state.currentQuestion?.correctAnswer ??
0,
onNotifTap: (AnswerEntity answer) {
context
.read<QuestionBloc>()
.showAnswerDialog(
context: context,
answerEntity: answer,
);
},
onTap: (isCorrect, correctAnswer) =>
context.read<QuestionBloc>().add(
ChooseAnswerEvent(
isCorrect,
correctAnswer,
context,
),
),
),
),
);
}
},
),
),
Expanded(
child: Builder(
key: Key('${state.currentQuestion?.id}3'),
builder: (context) { builder: (context) {
if (state.currentQuestion?.answers?[3].imageId == if (state.currentQuestion?.answers?[3].imageId ==
null) { null) {
@ -342,7 +409,8 @@ class _QuestionScreenState extends State<QuestionScreen>
state.currentQuestion?.answers?[3] ?? state.currentQuestion?.answers?[3] ??
AnswerEntity(), AnswerEntity(),
correctAnswer: correctAnswer:
state.currentQuestion?.correctAnswer ?? 0,
state.currentQuestion?.correctAnswer ??
0,
onNotifTap: (AnswerEntity answer) { onNotifTap: (AnswerEntity answer) {
context context
.read<QuestionBloc>() .read<QuestionBloc>()
@ -365,6 +433,7 @@ class _QuestionScreenState extends State<QuestionScreen>
} }
}, },
), ),
),
], ],
), ),
], ],
@ -393,13 +462,27 @@ class _QuestionScreenState extends State<QuestionScreen>
left: 90, left: 90,
right: 90, right: 90,
child: FadeAnimController( child: FadeAnimController(
controller: context.read<QuestionBloc>().imageAnimationController!,
controller: context
.read<QuestionBloc>()
.imageAnimationController!,
child: TextButton( child: TextButton(
onPressed: () async { onPressed: () async {
if(context.read<QuestionBloc>().imageAnimationController?.isForwardOrCompleted ?? false){
context.read<QuestionBloc>().imageAnimationController?.reverse();
context.read<QuestionBloc>().answerAnimationController?.forward();
context.read<QuestionBloc>().showingAnswerSequence(show: false);
if (context
.read<QuestionBloc>()
.imageAnimationController
?.isForwardOrCompleted ??
false) {
context
.read<QuestionBloc>()
.imageAnimationController
?.reverse();
context
.read<QuestionBloc>()
.answerAnimationController
?.forward();
context.read<QuestionBloc>().showingAnswerSequence(
show: false,
);
context.read<QuestionBloc>().pausePlaying(); context.read<QuestionBloc>().pausePlaying();
} }
}, },
@ -412,7 +495,7 @@ class _QuestionScreenState extends State<QuestionScreen>
style: MYTextStyle.button2, style: MYTextStyle.button2,
), ),
), ),
)
),
), ),
), ),
PositionedDirectional( PositionedDirectional(
@ -429,4 +512,3 @@ class _QuestionScreenState extends State<QuestionScreen>
); );
} }
} }
Loading…
Cancel
Save