Browse Source

update

develop
sina 2 days ago
parent
commit
cd555aa141
  1. BIN
      assets/videos/intro_1.mp4
  2. BIN
      assets/videos/intro_1_ar.mp4
  3. BIN
      assets/videos/intro_1_en.mp4
  4. BIN
      assets/videos/intro_2.mp4
  5. BIN
      assets/videos/intro_2_ar.mp4
  6. BIN
      assets/videos/intro_2_en.mp4
  7. BIN
      assets/videos/intro_3.mp4
  8. BIN
      assets/videos/intro_3_ar.mp4
  9. BIN
      assets/videos/intro_3_en.mp4
  10. BIN
      assets/videos/intro_4.mp4
  11. BIN
      assets/videos/intro_4_ar.mp4
  12. BIN
      assets/videos/intro_4_en.mp4
  13. BIN
      assets/videos/intro_5.mp4
  14. BIN
      assets/videos/intro_5_ar.mp4
  15. BIN
      assets/videos/intro_5_en.mp4
  16. 8
      lib/core/widgets/answer_box/answer_box.dart
  17. 1
      lib/core/widgets/answer_box/answer_box_show.dart
  18. 24
      lib/features/intro/presentation/bloc/intro_bloc.dart
  19. 53
      lib/features/level/presentation/bloc/level_bloc.dart
  20. 142
      lib/features/level/presentation/ui/level_page.dart
  21. 39
      lib/features/level/presentation/ui/widgets/node_widget.dart
  22. 1
      lib/features/question/presentation/bloc/question_bloc.dart
  23. 98
      lib/features/question/presentation/ui/screens/question_screen.dart

BIN
assets/videos/intro_1.mp4

BIN
assets/videos/intro_1_ar.mp4

BIN
assets/videos/intro_1_en.mp4

BIN
assets/videos/intro_2.mp4

BIN
assets/videos/intro_2_ar.mp4

BIN
assets/videos/intro_2_en.mp4

BIN
assets/videos/intro_3.mp4

BIN
assets/videos/intro_3_ar.mp4

BIN
assets/videos/intro_3_en.mp4

BIN
assets/videos/intro_4.mp4

BIN
assets/videos/intro_4_ar.mp4

BIN
assets/videos/intro_4_en.mp4

BIN
assets/videos/intro_5.mp4

BIN
assets/videos/intro_5_ar.mp4

BIN
assets/videos/intro_5_en.mp4

8
lib/core/widgets/answer_box/answer_box.dart

@ -68,9 +68,13 @@ class _AnswerBoxState extends State<AnswerBox> {
left: 0, left: 0,
right: 0, right: 0,
bottom: 0, bottom: 0,
child: AnswerTextBox(text: widget.answer.title ?? ''),
child: AnswerTextBox(
text: widget.answer.title ?? '',
padding: const EdgeInsetsGeometry.all(10),
), ),
if(widget.answer.audioInfo?.filename?.isNotEmpty == true)Positioned(
),
if (widget.answer.audioInfo?.filename?.isNotEmpty == true)
Positioned(
top: setSize( top: setSize(
context: context, context: context,
mobile: MySpaces.s12, mobile: MySpaces.s12,

1
lib/core/widgets/answer_box/answer_box_show.dart

@ -46,6 +46,7 @@ class AnswerBoxShow extends StatelessWidget {
padding: const EdgeInsetsGeometry.all(14), padding: const EdgeInsetsGeometry.all(14),
), ),
), ),
if (answer.audioInfo?.filename?.isNotEmpty == true)
Positioned( Positioned(
top: setSize(context: context, mobile: MySpaces.s30, tablet: 60), top: setSize(context: context, mobile: MySpaces.s30, tablet: 60),
right: setSize( right: setSize(

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

@ -45,22 +45,24 @@ class IntroBloc extends Bloc<IntroEvent, IntroState> {
Intro4Screen(key: Key('3')), Intro4Screen(key: Key('3')),
Intro5Screen(key: Key('4')), Intro5Screen(key: Key('4')),
]; ];
late final _supportedIntroLangs = const ['en', 'ar'];
late final _lang = LocalStorage.readData(key: MyConstants.selectLanguage) ?? MyConstants.defaultLanguage;
late final _introLang = _supportedIntroLangs.contains(_lang) ? _lang : MyConstants.defaultLanguage;
/// ------------Controllers------------ /// ------------Controllers------------
final PodPlayerController podController1 = PodPlayerController(
playVideoFrom: PlayVideoFrom.asset('assets/videos/intro_1.mp4'),
late final PodPlayerController podController1 = PodPlayerController(
playVideoFrom: PlayVideoFrom.asset('assets/videos/intro_1_$_introLang.mp4'),
); );
final PodPlayerController podController2 = PodPlayerController(
playVideoFrom: PlayVideoFrom.asset('assets/videos/intro_2.mp4'),
late final PodPlayerController podController2 = PodPlayerController(
playVideoFrom: PlayVideoFrom.asset('assets/videos/intro_2_$_introLang.mp4'),
); );
final PodPlayerController podController3 = PodPlayerController(
playVideoFrom: PlayVideoFrom.asset('assets/videos/intro_3.mp4'),
late final PodPlayerController podController3 = PodPlayerController(
playVideoFrom: PlayVideoFrom.asset('assets/videos/intro_3_$_introLang.mp4'),
); );
final PodPlayerController podController4 = PodPlayerController(
playVideoFrom: PlayVideoFrom.asset('assets/videos/intro_4.mp4'),
late final PodPlayerController podController4 = PodPlayerController(
playVideoFrom: PlayVideoFrom.asset('assets/videos/intro_4_$_introLang.mp4'),
); );
final PodPlayerController podController5 = PodPlayerController(
playVideoFrom: PlayVideoFrom.asset('assets/videos/intro_5.mp4'),
late final PodPlayerController podController5 = PodPlayerController(
playVideoFrom: PlayVideoFrom.asset('assets/videos/intro_5_$_introLang.mp4'),
); );
/// ------------Functions------------ /// ------------Functions------------

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

@ -117,71 +117,78 @@ class LevelBloc extends Bloc<LevelEvent, LevelState> {
left: setSize(context: MyContext.get, mobile: 0.15.w, tablet: 0.58.w), left: setSize(context: MyContext.get, mobile: 0.15.w, tablet: 0.58.w),
index: 11, index: 11,
), ),
//////
LevelLocation( LevelLocation(
bottom: setSize(context: MyContext.get, mobile: 0.78.h, tablet: 1.52.h), 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), left: setSize(context: MyContext.get, mobile: 0.4.w, tablet: 0.45.w),
index: 12, index: 12,
), ),
/////
LevelLocation( LevelLocation(
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),
bottom: setSize(context: MyContext.get, mobile: 0.78.h, tablet: 1.52.h),
left: setSize(context: MyContext.get, mobile: 0.35.w, tablet: 0.55.w),
index: 13, index: 13,
), ),
LevelLocation( LevelLocation(
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),
bottom: setSize(context: MyContext.get, mobile: 0.85.h, tablet: 1.62.h),
left: setSize(context: MyContext.get, mobile: 0.5.w, tablet: 0.46.w),
index: 14, index: 14,
), ),
LevelLocation( LevelLocation(
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),
bottom: setSize(context: MyContext.get, mobile: 0.94.h, tablet: 1.62.h),
left: setSize(context: MyContext.get, mobile: 0.45.w, tablet: 0.3.w),
index: 15, index: 15,
), ),
LevelLocation( LevelLocation(
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),
bottom: setSize(context: MyContext.get, mobile: 1.02.h, tablet: 1.62.h),
left: setSize(context: MyContext.get, mobile: 0.45.w, tablet: 0.11.w),
index: 16, index: 16,
), ),
LevelLocation( LevelLocation(
bottom: setSize(context: MyContext.get, mobile: 1.02.h, tablet: 2.0.h),
left: setSize(context: MyContext.get, mobile: 0, tablet: 0.1.w),
bottom: setSize(context: MyContext.get, mobile: 1.02.h, tablet: 1.7.h),
left: setSize(context: MyContext.get, mobile: 0.2.w, tablet: 0.0.w),
index: 17, index: 17,
), ),
LevelLocation( LevelLocation(
bottom: setSize(context: MyContext.get, mobile: 1.1.h, tablet: 2.17.h),
left: setSize(context: MyContext.get, mobile: 0, tablet: 0.04.w),
bottom: setSize(context: MyContext.get, mobile: 1.02.h, tablet: 1.825.h),
left: setSize(context: MyContext.get, mobile: 0, tablet: 0.0.w),
index: 18, index: 18,
), ),
LevelLocation( LevelLocation(
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),
bottom: setSize(context: MyContext.get, mobile: 1.1.h, tablet: 1.88.h),
left: setSize(context: MyContext.get, mobile: 0, tablet: 0.125.w),
index: 19, index: 19,
), ),
LevelLocation( LevelLocation(
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),
bottom: setSize(context: MyContext.get, mobile: 1.19.h, tablet: 1.97.h),
left: setSize(context: MyContext.get, mobile: 0.05.w, tablet: 0.289.w),
index: 20, index: 20,
), ),
LevelLocation( LevelLocation(
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),
bottom: setSize(context: MyContext.get, mobile: 1.23.h, tablet: 2.10.h),
left: setSize(context: MyContext.get, mobile: 0.23.w, tablet: 0.21.w),
index: 21, index: 21,
), ),
LevelLocation( LevelLocation(
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),
bottom: setSize(context: MyContext.get, mobile: 1.31.h, tablet: 2.169.h),
left: setSize(context: MyContext.get, mobile: 0.2.w, tablet: 0.1.w),
index: 22, index: 22,
), ),
LevelLocation( LevelLocation(
bottom: setSize(context: MyContext.get, mobile: 1.45.h, tablet: 2.7.h),
bottom: setSize(context: MyContext.get, mobile: 1.37.h, tablet: 2.25.h),
left: setSize(context: MyContext.get, mobile: 0.1.w, tablet: 0.1.w), left: setSize(context: MyContext.get, mobile: 0.1.w, tablet: 0.1.w),
index: 23, index: 23,
), ),
LevelLocation( LevelLocation(
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),
bottom: setSize(context: MyContext.get, mobile: 1.45.h, tablet: 2.34.h),
left: setSize(context: MyContext.get, mobile: 0.12.w, tablet: 0.225.w),
index: 24, index: 24,
), ),
// LevelLocation(
// 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,
// ),
]; ];
final List<NodeEntity> nodeList = []; final List<NodeEntity> nodeList = [];

142
lib/features/level/presentation/ui/level_page.dart

@ -1,3 +1,4 @@
import 'package:collection/collection.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
@ -27,6 +28,8 @@ import 'package:hadi_hoda_flutter/features/level/presentation/ui/widgets/level_p
import 'package:hadi_hoda_flutter/features/level/presentation/ui/widgets/node_widget.dart'; import 'package:hadi_hoda_flutter/features/level/presentation/ui/widgets/node_widget.dart';
import 'package:hadi_hoda_flutter/features/level/presentation/ui/widgets/play_button.dart'; import 'package:hadi_hoda_flutter/features/level/presentation/ui/widgets/play_button.dart';
import '../../domain/entity/level_location.dart';
class LevelPage extends StatefulWidget { class LevelPage extends StatefulWidget {
const LevelPage({super.key}); const LevelPage({super.key});
@ -40,14 +43,20 @@ class _LevelPageState extends State<LevelPage> {
@override @override
void initState() { void initState() {
super.initState(); super.initState();
if(!kDebugMode)_triggerRemainingLevelsDownload();
if (!kDebugMode) _triggerRemainingLevelsDownload();
} }
void _triggerRemainingLevelsDownload() { void _triggerRemainingLevelsDownload() {
WidgetsBinding.instance.addPostFrameCallback((_) { WidgetsBinding.instance.addPostFrameCallback((_) {
if (!mounted) return; if (!mounted) return;
final maxLevelCount = int.tryParse(LocalStorage.readData(key: MyConstants.maxLevelCount) ?? '20') ?? 20;
context.read<DownloadBloc>().add(StartDownloadEvent(toLevel: maxLevelCount));
final maxLevelCount =
int.tryParse(
LocalStorage.readData(key: MyConstants.maxLevelCount) ?? '20',
) ??
20;
context.read<DownloadBloc>().add(
StartDownloadEvent(toLevel: maxLevelCount),
);
}); });
} }
@ -68,7 +77,6 @@ class _LevelPageState extends State<LevelPage> {
_background(context), _background(context),
_planets(context), _planets(context),
_path(context), _path(context),
], ],
), ),
), ),
@ -78,12 +86,9 @@ class _LevelPageState extends State<LevelPage> {
child: Stack( child: Stack(
alignment: Alignment.center, alignment: Alignment.center,
clipBehavior: Clip.none, clipBehavior: Clip.none,
children: [
_ship(context),
_playButton(context),
],
children: [_ship(context), _playButton(context)],
),
), ),
)
], ],
), ),
), ),
@ -214,7 +219,21 @@ class _LevelPageState extends State<LevelPage> {
} }
Widget _path(BuildContext context) { Widget _path(BuildContext context) {
return BlocBuilder<LevelBloc, LevelState>(
builder: (context, state) {
final locationList = context.read<LevelBloc>().locationList;
final nodeList = context.read<LevelBloc>().nodeList;
final comingSoon = locationList.firstWhereIndexedOrNull((
index,
location,
) {
final node = nodeList.elementAtOrNull(index);
return node?.nodeType == NodeType.comingSoon;
});
return Positioned.fill( return Positioned.fill(
child: Stack(
children: [
Positioned.fill(
top: 250, top: 250,
bottom: 150, bottom: 150,
right: 50, right: 50,
@ -222,44 +241,64 @@ class _LevelPageState extends State<LevelPage> {
child: Stack( child: Stack(
alignment: Alignment.center, alignment: Alignment.center,
children: [ children: [
const Positioned.fill(
child: LevelPath(),
const Positioned.fill(child: LevelPath()),
Positioned.fill(
child: _levelLocation(
locationList: locationList,
nodeList: nodeList,
),
),
],
),
),
if (comingSoon != null) ...[
Positioned(
top: 0,
right: 0,
left: 0,
bottom: (comingSoon.bottom ?? 0) + 190,
child: _lockMapShadowCover(),
),
Positioned(
left: 50,
right: 50,
bottom: (comingSoon.bottom ?? 0) + 195,
child: const ComingSoonLevel(),
), ),
Positioned.fill(child: _levelLocation(context)),
],
], ],
), ),
); );
},
);
} }
Widget _levelLocation(BuildContext context) {
Widget _levelLocation({
required List<LevelLocation> locationList,
required List<NodeEntity> nodeList,
}) {
return BlocBuilder<LevelBloc, LevelState>( return BlocBuilder<LevelBloc, LevelState>(
builder: (context, state) => Stack(
builder: (context, state) {
return Stack(
clipBehavior: Clip.none, clipBehavior: Clip.none,
children: [ children: [
...List.generate(
context.read<LevelBloc>().nodeList.length,
(index) {
final node = context.read<LevelBloc>().nodeList[index];
if(node.nodeType == NodeType.comingSoon) {
if(node.nodeType == NodeType.comingSoon) {
return Positioned(
left: 0,
right: 0,
bottom: (context.read<LevelBloc>().locationList[index].bottom ?? 0) + 88,
child: const ComingSoonLevel());
}
}
...List.generate(locationList.length, (index) {
final node = nodeList.elementAtOrNull(index);
final location = locationList[index];
if (node?.nodeType == NodeType.comingSoon)
return const SizedBox();
return Positioned( return Positioned(
top: context.read<LevelBloc>().locationList[index].top,
bottom: context.read<LevelBloc>().locationList[index].bottom,
right: context.read<LevelBloc>().locationList[index].right,
left: context.read<LevelBloc>().locationList[index].left,
top: location.top,
bottom: location.bottom,
right: location.right,
left: location.left,
child: BlocBuilder<LevelBloc, LevelState>( child: BlocBuilder<LevelBloc, LevelState>(
buildWhen: (previous, current) => buildWhen: (previous, current) =>
previous.chooseLevel?.id != current.chooseLevel?.id, previous.chooseLevel?.id != current.chooseLevel?.id,
builder: (context, state) => NodeWidget( builder: (context, state) => NodeWidget(
chooseLevel: state.chooseLevel, chooseLevel: state.chooseLevel,
node: context.read<LevelBloc>().nodeList[index],
levelIndex: location.index,
node: node,
type: context.read<LevelBloc>().getLevelType, type: context.read<LevelBloc>().getLevelType,
getReward: context.read<LevelBloc>().getReward, getReward: context.read<LevelBloc>().getReward,
onRewardPressed: (prize) { onRewardPressed: (prize) {
@ -276,17 +315,15 @@ class _LevelPageState extends State<LevelPage> {
), ),
), ),
); );
},
),
}),
], ],
),
);
},
); );
} }
Widget _ship(BuildContext context) { Widget _ship(BuildContext context) {
return const ShipAnim(
child: MyImage(image: MyAssets.ship),
);
return const ShipAnim(child: MyImage(image: MyAssets.ship));
} }
Widget _playButton(BuildContext context) { Widget _playButton(BuildContext context) {
@ -299,7 +336,7 @@ class _LevelPageState extends State<LevelPage> {
onTap: (level) => onTap: (level) =>
context.read<LevelBloc>().goToQuestionPage(context, level), context.read<LevelBloc>().goToQuestionPage(context, level),
); );
}
},
); );
} }
@ -322,9 +359,7 @@ class _LevelPageState extends State<LevelPage> {
), ),
), ),
const Spacer(), const Spacer(),
DiamondLevel(
diamonds: context.read<LevelBloc>().diamonds,
),
DiamondLevel(diamonds: context.read<LevelBloc>().diamonds),
StreamBuilder<double>( StreamBuilder<double>(
initialData: 1, initialData: 1,
stream: context.read<LevelBloc>().volumeStream, stream: context.read<LevelBloc>().volumeStream,
@ -364,9 +399,26 @@ class _LevelPageState extends State<LevelPage> {
// } // }
Widget _background(BuildContext context) { Widget _background(BuildContext context) {
return const MyImage(
image: MyAssets.mapBackground,
fit: BoxFit.cover,
return const MyImage(image: MyAssets.mapBackground, fit: BoxFit.cover);
}
Widget _lockMapShadowCover() {
return Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
Colors.black.withValues(alpha: .8),
Colors.black54,
Colors.black54,
Colors.black54,
Colors.black54,
Colors.black54,
Colors.transparent,
],
begin: AlignmentGeometry.topCenter,
end: AlignmentGeometry.bottomCenter,
),
),
); );
} }
} }

39
lib/features/level/presentation/ui/widgets/node_widget.dart

@ -42,34 +42,39 @@ class NodeWidget extends StatelessWidget {
required this.getReward, required this.getReward,
required this.type, required this.type,
required this.chooseLevel, required this.chooseLevel,
required this.levelIndex,
this.onTap, this.onTap,
this.onRewardPressed, this.onRewardPressed,
}); });
final LevelType Function(int index) type; final LevelType Function(int index) type;
final bool Function(int index) getReward; final bool Function(int index) getReward;
final NodeEntity node;
final NodeEntity? node;
final int? levelIndex;
final LevelEntity? chooseLevel; final LevelEntity? chooseLevel;
final Function(LevelEntity level, LevelType type)? onTap; final Function(LevelEntity level, LevelType type)? onTap;
final void Function(PrizeEntity prize)? onRewardPressed; final void Function(PrizeEntity prize)? onRewardPressed;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Builder(
final levelIsInComingSoon = node == null || node?.nodeType == NodeType.comingSoon;
return AbsorbPointer(
absorbing: levelIsInComingSoon,
child: Opacity(
opacity: levelIsInComingSoon ? .85 : 1,
child: Builder(
builder: (context) { builder: (context) {
if (node.nodeType == NodeType.comingSoon) {
return const ComingSoonLevel();
} else if (node.nodeType == NodeType.prize) {
if (node?.nodeType == NodeType.prize) {
return MyInkwell( return MyInkwell(
onTap: () { onTap: () {
if (getReward(node.prize?.afterLevel ?? 1)) {
onRewardPressed?.call(node.prize ?? PrizeEntity());
if (getReward(node?.prize?.afterLevel ?? 1)) {
onRewardPressed?.call(node!.prize ?? PrizeEntity());
} }
}, },
child: Stack( child: Stack(
alignment: Alignment.center, alignment: Alignment.center,
children: [ children: [
if (getReward(node.prize?.afterLevel ?? 1)) ...{
if (getReward(node?.prize?.afterLevel ?? 1)) ...{
const MyImage(image: MyAssets.giftBackground, size: 70), const MyImage(image: MyAssets.giftBackground, size: 70),
const MyImage(image: MyAssets.gift, size: 50), const MyImage(image: MyAssets.gift, size: 50),
} else ...{ } else ...{
@ -83,8 +88,8 @@ class NodeWidget extends StatelessWidget {
offset: const Offset(-8, 8), offset: const Offset(-8, 8),
child: InkWell( child: InkWell(
onTap: () => onTap?.call( onTap: () => onTap?.call(
node.level ?? LevelEntity(),
type(node.level?.order ?? 1),
node?.level ?? LevelEntity(),
type(node?.level?.order ?? levelIndex ?? 1),
), ),
child: Container( child: Container(
color: Colors.transparent, color: Colors.transparent,
@ -95,7 +100,7 @@ class NodeWidget extends StatelessWidget {
children: [ children: [
MyImage( MyImage(
image: image:
LevelType.image[type(node.level?.order ?? 1)] ??
LevelType.image[type(node?.level?.order ?? levelIndex ?? 1)] ??
MyAssets.level, MyAssets.level,
fit: BoxFit.cover, fit: BoxFit.cover,
size: setSize(context: context, tablet: 70, mobile: 44), size: setSize(context: context, tablet: 70, mobile: 44),
@ -107,12 +112,12 @@ class NodeWidget extends StatelessWidget {
end: Alignment.bottomCenter, end: Alignment.bottomCenter,
colors: [ colors: [
const Color(0XFFFFFFFF), const Color(0XFFFFFFFF),
LevelType.textColor[type(node.level?.order ?? 1)] ??
LevelType.textColor[type(node?.level?.order ?? levelIndex ?? 1)] ??
MyColors.white, MyColors.white,
], ],
).createShader(bounds), ).createShader(bounds),
child: Text( child: Text(
'${node.level?.order ?? 0}',
'${node?.level?.order ?? levelIndex ?? 0}',
maxLines: 1, maxLines: 1,
style: MYTextStyle.button1.copyWith( style: MYTextStyle.button1.copyWith(
fontSize: setSize( fontSize: setSize(
@ -124,7 +129,7 @@ class NodeWidget extends StatelessWidget {
BoxShadow( BoxShadow(
color: color:
LevelType.textShadowColor[type( LevelType.textShadowColor[type(
node.level?.order ?? 1,
node?.level?.order ?? levelIndex ?? 1,
)] ?? )] ??
MyColors.white, MyColors.white,
offset: const Offset(0, 2.97), offset: const Offset(0, 2.97),
@ -133,7 +138,7 @@ class NodeWidget extends StatelessWidget {
), ),
), ),
), ),
if (node.level?.id == chooseLevel?.id)
if (node?.level?.id == chooseLevel?.id)
Positioned( Positioned(
top: setSize( top: setSize(
context: context, context: context,
@ -149,7 +154,7 @@ class NodeWidget extends StatelessWidget {
), ),
), ),
), ),
if (type(node.level?.order ?? 1) == LevelType.finished)
if (type(node?.level?.order ?? levelIndex ?? 1) == LevelType.finished)
Positioned( Positioned(
bottom: 0, bottom: 0,
child: Container( child: Container(
@ -186,6 +191,8 @@ class NodeWidget extends StatelessWidget {
); );
} }
}, },
),
),
); );
} }
} }

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

@ -318,6 +318,7 @@ class QuestionBloc extends Bloc<QuestionEvent, QuestionState> {
AnswerEntity(), AnswerEntity(),
showConfetti: true, showConfetti: true,
); );
scrollController.jumpTo(0);
answerAnimationController?.reverse(); answerAnimationController?.reverse();
await Future.delayed(const Duration(seconds: 1), () async { await Future.delayed(const Duration(seconds: 1), () async {
final QuestionEntity? findPreQuestion = state.currentQuestion; final QuestionEntity? findPreQuestion = state.currentQuestion;

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

@ -37,6 +37,8 @@ class QuestionScreen extends StatefulWidget {
class _QuestionScreenState extends State<QuestionScreen> class _QuestionScreenState extends State<QuestionScreen>
with TickerProviderStateMixin, WidgetsBindingObserver { with TickerProviderStateMixin, WidgetsBindingObserver {
late final isTablet = MyDevice.isTablet(context); late final isTablet = MyDevice.isTablet(context);
late final boxRation = isTablet ? 320 / 300 : 180 / 250;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
@ -99,6 +101,7 @@ class _QuestionScreenState extends State<QuestionScreen>
return FadeAnimController( return FadeAnimController(
controller: context.read<QuestionBloc>().imageAnimationController!, controller: context.read<QuestionBloc>().imageAnimationController!,
child: SingleChildScrollView( child: SingleChildScrollView(
controller: context.read<QuestionBloc>().scrollController,
child: Column( child: Column(
children: [ children: [
_titles(context), _titles(context),
@ -190,10 +193,12 @@ class _QuestionScreenState extends State<QuestionScreen>
null) { null) {
return const SizedBox.shrink(); return const SizedBox.shrink();
} else { } else {
return Container(
return AspectRatio(
aspectRatio: boxRation,
child: Container(
alignment: isTablet ? Alignment.center : null, alignment: isTablet ? Alignment.center : null,
width: isTablet ? 320 : 180, width: isTablet ? 320 : 180,
height: isTablet ? 300 :250,
height: isTablet ? 300 : 250,
child: SlideAnim( child: SlideAnim(
controller: context controller: context
.read<QuestionBloc>() .read<QuestionBloc>()
@ -210,7 +215,10 @@ class _QuestionScreenState extends State<QuestionScreen>
state.currentQuestion?.answers?[0] ?? state.currentQuestion?.answers?[0] ??
AnswerEntity(), AnswerEntity(),
correctAnswer: correctAnswer:
state.currentQuestion?.correctAnswer ?? 0,
state
.currentQuestion
?.correctAnswer ??
0,
onNotifTap: (AnswerEntity answer) { onNotifTap: (AnswerEntity answer) {
context context
.read<QuestionBloc>() .read<QuestionBloc>()
@ -229,6 +237,7 @@ class _QuestionScreenState extends State<QuestionScreen>
), ),
), ),
), ),
),
); );
} }
}, },
@ -242,10 +251,12 @@ class _QuestionScreenState extends State<QuestionScreen>
null) { null) {
return const SizedBox.shrink(); return const SizedBox.shrink();
} else { } else {
return Container(
return AspectRatio(
aspectRatio: boxRation,
child: Container(
alignment: isTablet ? Alignment.center : null, alignment: isTablet ? Alignment.center : null,
width: isTablet ? 320 : 180, width: isTablet ? 320 : 180,
height: isTablet ? 300 :250,
height: isTablet ? 300 : 250,
child: SlideAnim( child: SlideAnim(
controller: context controller: context
.read<QuestionBloc>() .read<QuestionBloc>()
@ -262,7 +273,10 @@ class _QuestionScreenState extends State<QuestionScreen>
state.currentQuestion?.answers?[1] ?? state.currentQuestion?.answers?[1] ??
AnswerEntity(), AnswerEntity(),
correctAnswer: correctAnswer:
state.currentQuestion?.correctAnswer ?? 0,
state
.currentQuestion
?.correctAnswer ??
0,
onNotifTap: (AnswerEntity answer) { onNotifTap: (AnswerEntity answer) {
context context
.read<QuestionBloc>() .read<QuestionBloc>()
@ -281,6 +295,7 @@ class _QuestionScreenState extends State<QuestionScreen>
), ),
), ),
), ),
),
); );
} }
}, },
@ -300,10 +315,12 @@ class _QuestionScreenState extends State<QuestionScreen>
null) { null) {
return const SizedBox.shrink(); return const SizedBox.shrink();
} else { } else {
return Container(
return AspectRatio(
aspectRatio: boxRation,
child: Container(
alignment: isTablet ? Alignment.center : null, alignment: isTablet ? Alignment.center : null,
width: isTablet ? 320 : 180, width: isTablet ? 320 : 180,
height: isTablet ? 300 :250,
height: isTablet ? 300 : 250,
child: SlideAnim( child: SlideAnim(
controller: context controller: context
.read<QuestionBloc>() .read<QuestionBloc>()
@ -320,7 +337,10 @@ class _QuestionScreenState extends State<QuestionScreen>
state.currentQuestion?.answers?[2] ?? state.currentQuestion?.answers?[2] ??
AnswerEntity(), AnswerEntity(),
correctAnswer: correctAnswer:
state.currentQuestion?.correctAnswer ?? 0,
state
.currentQuestion
?.correctAnswer ??
0,
onNotifTap: (AnswerEntity answer) { onNotifTap: (AnswerEntity answer) {
context context
.read<QuestionBloc>() .read<QuestionBloc>()
@ -339,6 +359,7 @@ class _QuestionScreenState extends State<QuestionScreen>
), ),
), ),
), ),
),
); );
} }
}, },
@ -358,10 +379,14 @@ class _QuestionScreenState extends State<QuestionScreen>
null) { null) {
return const SizedBox.shrink(); return const SizedBox.shrink();
} else { } else {
return Container(
alignment: isTablet ? Alignment.center : null,
return AspectRatio(
aspectRatio: boxRation,
child: Container(
alignment: isTablet
? Alignment.center
: null,
width: isTablet ? 320 : 180, width: isTablet ? 320 : 180,
height: isTablet ? 300 :250,
height: isTablet ? 300 : 250,
child: SlideAnim( child: SlideAnim(
controller: context controller: context
.read<QuestionBloc>() .read<QuestionBloc>()
@ -375,10 +400,14 @@ class _QuestionScreenState extends State<QuestionScreen>
.order ?? .order ??
1, 1,
answer: answer:
state.currentQuestion?.answers?[2] ??
state
.currentQuestion
?.answers?[2] ??
AnswerEntity(), AnswerEntity(),
correctAnswer: correctAnswer:
state.currentQuestion?.correctAnswer ??
state
.currentQuestion
?.correctAnswer ??
0, 0,
onNotifTap: (AnswerEntity answer) { onNotifTap: (AnswerEntity answer) {
context context
@ -398,6 +427,7 @@ class _QuestionScreenState extends State<QuestionScreen>
), ),
), ),
), ),
),
); );
} }
}, },
@ -411,10 +441,14 @@ class _QuestionScreenState extends State<QuestionScreen>
null) { null) {
return const SizedBox.shrink(); return const SizedBox.shrink();
} else { } else {
return Container(
alignment: isTablet ? Alignment.center : null,
return AspectRatio(
aspectRatio: boxRation,
child: Container(
alignment: isTablet
? Alignment.center
: null,
width: isTablet ? 320 : 180, width: isTablet ? 320 : 180,
height: isTablet ? 300 :250,
height: isTablet ? 300 : 250,
child: SlideAnim( child: SlideAnim(
controller: context controller: context
.read<QuestionBloc>() .read<QuestionBloc>()
@ -428,10 +462,14 @@ class _QuestionScreenState extends State<QuestionScreen>
.order ?? .order ??
1, 1,
answer: answer:
state.currentQuestion?.answers?[3] ??
state
.currentQuestion
?.answers?[3] ??
AnswerEntity(), AnswerEntity(),
correctAnswer: correctAnswer:
state.currentQuestion?.correctAnswer ??
state
.currentQuestion
?.correctAnswer ??
0, 0,
onNotifTap: (AnswerEntity answer) { onNotifTap: (AnswerEntity answer) {
context context
@ -451,6 +489,7 @@ class _QuestionScreenState extends State<QuestionScreen>
), ),
), ),
), ),
),
); );
} }
}, },
@ -475,24 +514,21 @@ class _QuestionScreenState extends State<QuestionScreen>
alignment: AlignmentDirectional.centerStart, alignment: AlignmentDirectional.centerStart,
children: [ children: [
AnimatedBuilder( AnimatedBuilder(
animation: context
.read<QuestionBloc>()
.globeAnimationController!,
builder: (context, child) =>
Gif(
image: AssetImage(context
.read<QuestionBloc>()
.statesGlobe[context
animation: context.read<QuestionBloc>().globeAnimationController!,
builder: (context, child) => Gif(
image: AssetImage(
context.read<QuestionBloc>().statesGlobe[context
.read<QuestionBloc>() .read<QuestionBloc>()
.globeAnimationController .globeAnimationController
?.value ?? ?.value ??
0] ?? 0] ??
MyAnimations.globeStateSpeaking),
MyAnimations.globeStateSpeaking,
),
fps: 10, fps: 10,
autostart: Autostart.loop, autostart: Autostart.loop,
width: 80, width: 80,
height: 80, height: 80,
)
),
), ),
Positioned( Positioned(
left: 90, left: 90,
@ -520,7 +556,9 @@ class _QuestionScreenState extends State<QuestionScreen>
show: false, show: false,
); );
context.read<QuestionBloc>().pausePlaying(); context.read<QuestionBloc>().pausePlaying();
context.read<QuestionBloc>().changeGlobeState(key: MyAnimations.globeStateNormal);
context.read<QuestionBloc>().changeGlobeState(
key: MyAnimations.globeStateNormal,
);
} }
}, },
style: TextButton.styleFrom( style: TextButton.styleFrom(

Loading…
Cancel
Save