Browse Source

Merge pull request 'change somethings' (#64) from fix/bugs into develop

Reviewed-on: https://git.nwhco.ir/amirreza.chegini/hade_hoda_flutter/pulls/64
develop
amirreza.chegini 5 hours ago
parent
commit
923eda535d
  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/middlewares/my_middlewares.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/features/download/presentation/bloc/download_bloc.dart';
import 'package:hadi_hoda_flutter/features/download/presentation/bloc/download_event.dart';
@ -52,15 +53,6 @@ GoRouter _appPages() => GoRouter(
initialLocation: Routes.splashPage,
navigatorKey: MyContext.rootNavigatorKey,
routes: [
GoRoute(
name: Routes.introPage,
path: Routes.introPage,
redirect: MyMiddlewares.intro,
builder: (context, state) => BlocProvider(
create: (context) => IntroBloc(),
child: const IntroPage(),
),
),
GoRoute(
name: Routes.samplePage,
path: Routes.samplePage,
@ -81,42 +73,60 @@ GoRouter _appPages() => GoRouter(
GoRoute(
name: 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(),
),
),
),
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(
name: Routes.languagePage,
path: Routes.languagePage,
builder: (context, state) => BlocProvider(
pageBuilder: (context, state) => myPageTransition(
key: state.pageKey,
child: BlocProvider(
create: (context) => LanguageBloc()..add(const InitLanguageEvent()),
child: const LanguagePage(),
),
),
),
GoRoute(
name: 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.effectAudioService),
),
child: const HomePage(),
),
),
),
GoRoute(
name: 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(instanceName: MyConstants.mainAudioService),
locator(instanceName: MyConstants.effectAudioService),
@ -124,23 +134,28 @@ GoRouter _appPages() => GoRouter(
child: const LevelPage(),
),
),
),
GoRoute(
name: Routes.guiderPage,
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(),
),
),
),
GoRoute(
name: Routes.questionPage,
path: '${Routes.questionPage}/:id',
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(instanceName: MyConstants.mainAudioService),
@ -149,11 +164,14 @@ GoRouter _appPages() => GoRouter(
child: const QuestionPage(),
),
),
),
GoRoute(
name: 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,
height: context.heightScreen,
image: FileImage(File(image)),
fps: 15,
fps: 20,
autostart: autostart,
fit: BoxFit.cover,
color: MyColors.black,
@ -63,7 +63,7 @@ class AnswerPictureBox extends StatelessWidget {
width: context.widthScreen,
height: context.heightScreen,
image: FileImage(File(image)),
fps: 15,
fps: 20,
autostart: autostart,
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_button.dart';
Future<void> showExitDialog({required BuildContext context, bool? backHome}) async {
Future<void> showExitDialog({
required BuildContext context,
bool? backHome,
bool? backLevel,
}) async {
await showDialog(
context: context,
builder: (context) => ExitDialog(backHome: backHome),
builder: (context) => ExitDialog(backHome: backHome, backLevel: backLevel),
barrierColor: MyColors.purple.withValues(alpha: 0.82),
useSafeArea: false,
);
}
class ExitDialog extends StatelessWidget {
const ExitDialog({super.key, this.backHome});
const ExitDialog({super.key, this.backHome, this.backLevel});
final bool? backHome;
final bool? backLevel;
@override
Widget build(BuildContext context) {
@ -35,7 +40,8 @@ class ExitDialog extends StatelessWidget {
child: Center(
child: Padding(
padding: EdgeInsets.symmetric(
horizontal: setSize(context: context, mobile: 18, tablet: 160) ?? 0,
horizontal:
setSize(context: context, mobile: 18, tablet: 160) ?? 0,
),
child: DialogBackground(
height: 260,
@ -44,11 +50,15 @@ class ExitDialog extends StatelessWidget {
children: [
Text(
context.translate.want_to_exit,
style: MYTextStyle.titr0.copyWith(color: const Color(0XFF322386)),
style: MYTextStyle.titr0.copyWith(
color: const Color(0XFF322386),
),
),
Text(
context.translate.exit_dialog_desc,
style: MYTextStyle.titr3.copyWith(color: const Color(0XFF6272A9)),
style: MYTextStyle.titr3.copyWith(
color: const Color(0XFF6272A9),
),
textAlign: TextAlign.center,
),
Row(
@ -79,6 +89,8 @@ class ExitDialog extends StatelessWidget {
onTap: () {
if (backHome ?? false) {
context.goNamed(Routes.homePage);
} else if (backLevel ?? false) {
context.goNamed(Routes.levelPage);
} else {
SystemNavigator.pop();
}

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

@ -89,9 +89,15 @@ class RewardDialog extends StatelessWidget {
children: [
Image.network(
prize.imageURL ?? '',
loadingBuilder: (context, child, loadingProgress) => SizedBox(
errorBuilder: (context, error, stackTrace) => Container(
height: 300,
width: 300,
color: const Color(0XFFE0E0E0),
),
loadingBuilder: (context, child, loadingProgress) => Container(
height: 300,
width: 300,
color: const Color(0XFFE0E0E0),
child: child,
),
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';
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 bool? backHome;
final bool? backLevel;
void onPopInvokedWithResult(
bool didPop,
dynamic result,
BuildContext context,
) {
showExitDialog(context: context, backHome: backHome);
showExitDialog(context: context, backHome: backHome, backLevel: backLevel);
}
@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),
end: MySpaces.s16,
child: SlideDownFade(
delay: const Duration(milliseconds: 200),
delay: const Duration(milliseconds: 100),
child: StreamBuilder<double>(
initialData: 1,
stream: context.read<HomeBloc>().volumeStream,
@ -91,7 +91,7 @@ class HomePage extends StatelessWidget {
right: MySpaces.s16,
child: SafeArea(
child: SlideUpFade(
delay: const Duration(milliseconds: 200),
delay: const Duration(milliseconds: 100),
child: Row(
crossAxisAlignment: CrossAxisAlignment.end,
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,
String? correctAudio,
bool showConfetti = false,
bool autoClose = false,
bool autoClose = true,
}) async {
await Navigator.of(context).push(
HeroDialogRoute(

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

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

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

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