diff --git a/assets/images/gift.png b/assets/images/gift.png new file mode 100644 index 0000000..1dfe4c4 Binary files /dev/null and b/assets/images/gift.png differ diff --git a/assets/images/gift_background.png b/assets/images/gift_background.png new file mode 100644 index 0000000..ad96c61 Binary files /dev/null and b/assets/images/gift_background.png differ diff --git a/assets/images/gift_disable.png b/assets/images/gift_disable.png new file mode 100644 index 0000000..d161107 Binary files /dev/null and b/assets/images/gift_disable.png differ diff --git a/assets/svg/icon_play_video.svg b/assets/svg/icon_play_video.svg new file mode 100644 index 0000000..5386a41 --- /dev/null +++ b/assets/svg/icon_play_video.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/lib/common_ui/resources/my_assets.dart b/lib/common_ui/resources/my_assets.dart index 2153575..59ccf34 100644 --- a/lib/common_ui/resources/my_assets.dart +++ b/lib/common_ui/resources/my_assets.dart @@ -36,6 +36,9 @@ class MyAssets { static const String satellite = 'assets/images/satellite.png'; static const String planetFinal = 'assets/images/planet_final.png'; static const String behindDiamond = 'assets/images/behind_diamond.png'; + static const String gift = 'assets/images/gift.png'; + static const String giftDisable = 'assets/images/gift_disable.png'; + static const String giftBackground = 'assets/images/gift_background.png'; /// SVG static const String closeBtn = 'assets/svg/close_btn.svg'; @@ -69,6 +72,7 @@ class MyAssets { static const String diamondContainer = 'assets/svg/diamond_container.svg'; static const String iconPlay = 'assets/svg/icon_play.svg'; static const String iconNotif = 'assets/svg/icon_notif.svg'; + static const String iconPlayVideo = 'assets/svg/icon_play_video.svg'; static final List images = [ backgroundHome, @@ -103,5 +107,8 @@ class MyAssets { satellite, planetFinal, behindDiamond, + gift, + giftDisable, + giftBackground, ]; } \ No newline at end of file diff --git a/lib/core/constants/my_api.dart b/lib/core/constants/my_api.dart index 0e24eaa..a8aebd5 100644 --- a/lib/core/constants/my_api.dart +++ b/lib/core/constants/my_api.dart @@ -10,7 +10,7 @@ class MyApi { static const String baseUrl = 'https://hadihoda.newhorizonco.uk/api'; - static const String levels = '/quiz/optimized/v2/levels/'; + static const String levels = '/quiz/optimized/v3/levels/'; static const String images = '/quiz/optimized/download-all-files/images/'; static const String audios = '/quiz/optimized/v2/download-all-files/audio/'; } diff --git a/lib/core/routers/my_routes.dart b/lib/core/routers/my_routes.dart index bab2866..e149e3c 100644 --- a/lib/core/routers/my_routes.dart +++ b/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/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'; import 'package:hadi_hoda_flutter/features/download/presentation/ui/download_page.dart'; @@ -42,6 +43,7 @@ class Routes { static const String questionPage = '/question_page'; static const String guiderPage = '/guider_page'; static const String levelPage = '/level_page'; + static const String videoPage = '/video_page'; } final GoRouter appPages = _appPages(); @@ -147,5 +149,11 @@ GoRouter _appPages() => GoRouter( child: const QuestionPage(), ), ), + GoRoute( + name: Routes.videoPage, + path: Routes.videoPage, + builder: (context, state) => + MyVideoPlayer(videoURL: state.extra as String), + ), ], ); \ No newline at end of file diff --git a/lib/core/widgets/dialog/reward_dialog.dart b/lib/core/widgets/dialog/reward_dialog.dart new file mode 100644 index 0000000..cb63843 --- /dev/null +++ b/lib/core/widgets/dialog/reward_dialog.dart @@ -0,0 +1,381 @@ +import 'dart:ui'; + +import 'package:flutter/material.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_assets.dart'; +import 'package:hadi_hoda_flutter/common_ui/resources/my_colors.dart'; +import 'package:hadi_hoda_flutter/common_ui/resources/my_text_style.dart'; +import 'package:hadi_hoda_flutter/core/routers/my_routes.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/set_platform_size.dart'; +import 'package:hadi_hoda_flutter/core/widgets/dialog/styles/dialog_background.dart'; +import 'package:hadi_hoda_flutter/core/widgets/images/my_image.dart'; +import 'package:hadi_hoda_flutter/features/level/domain/entity/prize_entity.dart'; +import 'package:lottie/lottie.dart'; + +Future showRewardDialog({ + required BuildContext context, + required PrizeEntity prize, +}) async { + await showDialog( + context: context, + builder: (context) => RewardDialog(prize: prize), + barrierColor: MyColors.purple.withValues(alpha: 0.82), + useSafeArea: false, + ); +} + +class RewardDialog extends StatelessWidget { + const RewardDialog({super.key, required this.prize}); + + final PrizeEntity prize; + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: MyColors.transparent, + body: BackdropFilter( + filter: ImageFilter.blur(sigmaX: 6, sigmaY: 6), + child: Center( + child: Padding( + padding: EdgeInsets.symmetric( + horizontal: + setSize(context: context, mobile: 18, tablet: 120) ?? 0, + ), + child: Stack( + alignment: Alignment.center, + children: [ + Lottie.asset( + MyAnimations.confetti, + height: context.heightScreen, + fit: BoxFit.cover, + ), + Stack( + clipBehavior: Clip.none, + children: [ + DialogBackground( + child: Column( + spacing: 34, + children: [ + Text( + context.translate.reward, + style: MYTextStyle.titr0.copyWith( + color: Color(0XFF322386), + fontSize: 22, + ), + ), + Text( + prize.title ?? '', + style: MYTextStyle.titr0.copyWith( + color: Color(0XFF322386), + fontSize: 22, + ), + ), + CustomPaint( + painter: _CustomShapePainter(), + child: ClipPath( + clipper: _CustomShapeClipper(), + child: GestureDetector( + onTap: () { + context.pushNamed( + Routes.videoPage, + extra: prize.animationURL as String, + ); + }, + child: Stack( + alignment: Alignment.center, + children: [ + Image.network( + prize.imageURL ?? '', + fit: BoxFit.cover, + ), + MyImage( + image: MyAssets.iconPlayVideo, + ), + ], + ), + ), + ), + ), + ], + ), + ), + PositionedDirectional( + end: setSize(context: context, mobile: 30, tablet: 40), + top: -12, + child: GestureDetector( + onTap: context.pop, + behavior: HitTestBehavior.opaque, + child: MyImage( + image: MyAssets.closeBtn, + size: setSize(context: context, mobile: 40, tablet: 60), + ), + ), + ), + ], + ), + ], + ), + ), + ), + ), + ); + } +} + +class _CustomShapePainter extends CustomPainter { + @override + void paint(Canvas canvas, Size size) { + final Paint strokePaint = Paint() + ..color = Color(0XFFF2F7FF) + ..style = PaintingStyle.stroke + ..strokeWidth = 4; + + final Path path = _CustomShapeClipper().getClip(size); + canvas.drawPath(path, strokePaint); + } + + @override + bool shouldRepaint(covariant CustomPainter oldDelegate) { + return this != oldDelegate; + } +} + +class _CustomShapeClipper extends CustomClipper { + @override + Path getClip(Size size) { + // Original SVG dimensions to calculate the scaling factors. + final double originalWidth = 193.0; + final double originalHeight = 189.0; + + // Scaling factors to make the path responsive. + final double scaleX = size.width / originalWidth; + final double scaleY = size.height / originalHeight; + + // The path is defined using the scaled coordinates from the SVG. + final Path path = Path() + ..moveTo(148.483 * scaleX, 4.10254 * scaleY) + ..cubicTo( + 131.624 * scaleX, + 1.93333 * scaleY, + 111.221 * scaleX, + 1.00169 * scaleY, + 91.2451 * scaleX, + 1.2666 * scaleY, + ) + ..cubicTo( + 71.2667 * scaleX, + 1.53156 * scaleY, + 51.7626 * scaleX, + 2.99274 * scaleY, + 36.6973 * scaleX, + 5.59668 * scaleY, + ) + ..cubicTo( + 29.1597 * scaleX, + 6.8995 * scaleY, + 22.7796 * scaleX, + 8.48114 * scaleY, + 18.0205 * scaleX, + 10.3203 * scaleY, + ) + ..cubicTo( + 15.641 * scaleX, + 11.2399 * scaleY, + 13.7026 * scaleX, + 12.2101 * scaleY, + 12.2383 * scaleX, + 13.2188 * scaleY, + ) + ..cubicTo( + 10.7653 * scaleX, + 14.2333 * scaleY, + 9.84633 * scaleX, + 15.2359 * scaleY, + 9.3916 * scaleX, + 16.1904 * scaleY, + ) + ..cubicTo( + 8.252 * scaleX, + 18.5828 * scaleY, + 7.18153 * scaleX, + 22.466 * scaleY, + 6.2207 * scaleX, + 27.5654 * scaleY, + ) + ..cubicTo( + 5.26481 * scaleX, + 32.6387 * scaleY, + 4.43215 * scaleX, + 38.8273 * scaleY, + 3.73535 * scaleX, + 45.7744 * scaleY, + ) + ..cubicTo( + 2.34189 * scaleX, + 59.6675 * scaleY, + 1.49647 * scaleX, + 76.5363 * scaleY, + 1.27832 * scaleX, + 93.4678 * scaleY, + ) + ..cubicTo( + 1.06017 * scaleX, + 110.4 * scaleY, + 1.47057 * scaleX, + 127.372 * scaleY, + 2.58301 * scaleX, + 141.473 * scaleY, + ) + ..cubicTo( + 3.13928 * scaleX, + 148.524 * scaleY, + 3.86921 * scaleX, + 154.841 * scaleY, + 4.78125 * scaleX, + 160.068 * scaleY, + ) + ..cubicTo( + 5.69748 * scaleX, + 165.32 * scaleY, + 6.78334 * scaleX, + 169.385 * scaleY, + 8.01367 * scaleX, + 171.984 * scaleY, + ) + ..cubicTo( + 8.53417 * scaleX, + 173.084 * scaleY, + 9.59654 * scaleX, + 174.216 * scaleY, + 11.2891 * scaleX, + 175.343 * scaleY, + ) + ..cubicTo( + 12.9722 * scaleX, + 176.463 * scaleY, + 15.1988 * scaleX, + 177.524 * scaleY, + 17.9219 * scaleX, + 178.515 * scaleY, + ) + ..cubicTo( + 23.3679 * scaleX, + 180.496 * scaleY, + 30.6491 * scaleX, + 182.138 * scaleY, + 39.1807 * scaleX, + 183.437 * scaleY, + ) + ..cubicTo( + 56.2336 * scaleX, + 186.032 * scaleY, + 78.0934 * scaleX, + 187.222 * scaleY, + 99.8242 * scaleX, + 187.064 * scaleY, + ) + ..cubicTo( + 121.556 * scaleX, + 186.906 * scaleY, + 143.101 * scaleX, + 185.4 * scaleY, + 159.525 * scaleX, + 182.622 * scaleY, + ) + ..cubicTo( + 167.745 * scaleX, + 181.232 * scaleY, + 174.627 * scaleX, + 179.531 * scaleY, + 179.594 * scaleX, + 177.548 * scaleY, + ) + ..cubicTo( + 182.079 * scaleX, + 176.556 * scaleY, + 184.034 * scaleX, + 175.512 * scaleY, + 185.429 * scaleX, + 174.437 * scaleY, + ) + ..cubicTo( + 186.83 * scaleX, + 173.355 * scaleY, + 187.568 * scaleX, + 172.319 * scaleY, + 187.812 * scaleX, + 171.361 * scaleY, + ) + ..lineTo( + 187.812 * scaleX, + 171.361 * scaleY, + ) // In SVG, this was H (horizontal line), equivalent to lineTo in Flutter + ..cubicTo( + 189.156 * scaleX, + 166.074 * scaleY, + 190.148 * scaleX, + 155.525 * scaleY, + 190.773 * scaleX, + 142.157 * scaleY, + ) + ..cubicTo( + 191.396 * scaleX, + 128.832 * scaleY, + 191.651 * scaleX, + 112.822 * scaleY, + 191.552 * scaleX, + 96.6875 * scaleY, + ) + ..cubicTo( + 191.453 * scaleX, + 80.5539 * scaleY, + 191.001 * scaleX, + 64.3091 * scaleY, + 190.213 * scaleX, + 50.5156 * scaleY, + ) + ..cubicTo( + 189.423 * scaleX, + 36.6928 * scaleY, + 188.299 * scaleX, + 25.4153 * scaleY, + 186.876 * scaleX, + 19.167 * scaleY, + ) + ..cubicTo( + 186.404 * scaleX, + 17.0929 * scaleY, + 185.566 * scaleX, + 15.3424 * scaleY, + 184.087 * scaleX, + 14.1582 * scaleY, + ) + ..cubicTo( + 181.343 * scaleX, + 11.9613 * scaleY, + 176.72 * scaleX, + 9.98089 * scaleY, + 170.561 * scaleX, + 8.27539 * scaleY, + ) + ..cubicTo( + 164.434 * scaleX, + 6.579 * scaleY, + 156.914 * scaleX, + 5.18731 * scaleY, + 148.483 * scaleX, + 4.10254 * scaleY, + ) + ..close(); // Closes the path to form a complete shape. + + return path; + } + + @override + bool shouldReclip(covariant CustomClipper oldClipper) { + return this != oldClipper; + } +} diff --git a/lib/core/widgets/video/my_video_player.dart b/lib/core/widgets/video/my_video_player.dart new file mode 100644 index 0000000..7e37ffb --- /dev/null +++ b/lib/core/widgets/video/my_video_player.dart @@ -0,0 +1,76 @@ +import 'package:flutter/material.dart'; +import 'package:hadi_hoda_flutter/common_ui/resources/my_colors.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_device.dart'; +import 'package:hadi_hoda_flutter/init_bindings.dart'; +import 'package:pod_player/pod_player.dart'; + +class MyVideoPlayer extends StatefulWidget { + const MyVideoPlayer({super.key, required this.videoURL}); + + final String? videoURL; + + @override + State createState() => _MyVideoPlayerState(); +} + +class _MyVideoPlayerState extends State { + late final PodPlayerController _controller; + final AudioService _mainAudioService = locator( + instanceName: MyConstants.mainAudioService, + ); + final AudioService _effectAudioService = locator( + instanceName: MyConstants.effectAudioService, + ); + + @override + void initState() { + super.initState(); + _mainAudioService.stop(); + _effectAudioService.stop(); + _controller = PodPlayerController( + podPlayerConfig: PodPlayerConfig( + autoPlay: false, + isLooping: false, + wakelockEnabled: true, + ), + playVideoFrom: PlayVideoFrom.network(widget.videoURL ?? ''), + )..initialise(); + } + + @override + void dispose() { + _controller.dispose(); + _mainAudioService.play(); + _effectAudioService.play(); + MyDevice.setPortrait(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: MyColors.black, + extendBodyBehindAppBar: true, + appBar: AppBar( + backgroundColor: MyColors.transparent, + foregroundColor: MyColors.white, + ), + body: PodVideoPlayer( + controller: _controller, + matchVideoAspectRatioToFrame: true, + matchFrameAspectRatioToVideo: true, + videoAspectRatio: _controller.videoPlayerValue?.aspectRatio ?? 16 / 9, + podProgressBarConfig: PodProgressBarConfig(), + onToggleFullScreen: (isFullScreen) async { + if (isFullScreen) { + await MyDevice.setAllOrientations(); + } else { + await MyDevice.setPortrait(); + } + }, + ), + ); + } +} diff --git a/lib/features/download/data/datasource/download_datasource.dart b/lib/features/download/data/datasource/download_datasource.dart index 587574d..843d969 100644 --- a/lib/features/download/data/datasource/download_datasource.dart +++ b/lib/features/download/data/datasource/download_datasource.dart @@ -10,8 +10,8 @@ import 'package:hadi_hoda_flutter/core/response/base_response.dart'; import 'package:hadi_hoda_flutter/core/utils/local_storage.dart'; import 'package:hadi_hoda_flutter/core/utils/storage_path.dart'; import 'package:hadi_hoda_flutter/features/download/domain/entities/download_entity.dart'; -import 'package:hadi_hoda_flutter/features/level/data/model/level_model.dart'; -import 'package:hadi_hoda_flutter/features/level/domain/entity/level_entity.dart'; +import 'package:hadi_hoda_flutter/features/level/data/model/node_model.dart'; +import 'package:hadi_hoda_flutter/features/level/domain/entity/node_entity.dart'; import 'package:hadi_hoda_flutter/features/level/domain/entity/total_data_entity.dart'; import 'package:hive/hive.dart'; @@ -146,11 +146,11 @@ class DownloadDatasourceImpl implements IDownloadDatasource { path: MyApi.levels, queryParameters: {'lang': selectedLanguage}, ); - final List levels = BaseResponse.getDataList( - response?['result'], - (json) => LevelModel.fromJson(json), + final List levels = BaseResponse.getDataList( + response?['path'], + (json) => NodeModel.fromJson(json), ); - await data.add(TotalDataEntity(code: selectedLanguage, levels: levels)); + await data.add(TotalDataEntity(code: selectedLanguage, nodes: levels)); } } diff --git a/lib/features/guider/data/datasource/guider_datasource.dart b/lib/features/guider/data/datasource/guider_datasource.dart index b2c2a12..6816cf5 100644 --- a/lib/features/guider/data/datasource/guider_datasource.dart +++ b/lib/features/guider/data/datasource/guider_datasource.dart @@ -24,7 +24,7 @@ class GuiderDatasourceImpl implements IGuiderDatasource { (e) => e.code == selectedLanguage, orElse: () => TotalDataEntity(), ); - final LevelEntity? findLevel = findData.levels?.first; + final LevelEntity? findLevel = findData.nodes?.first.level; return findLevel ?? LevelEntity(); } catch (e) { throw MyException(errorMessage: '$e'); diff --git a/lib/features/home/presentation/bloc/home_bloc.dart b/lib/features/home/presentation/bloc/home_bloc.dart index 706dfa9..3389b8b 100644 --- a/lib/features/home/presentation/bloc/home_bloc.dart +++ b/lib/features/home/presentation/bloc/home_bloc.dart @@ -42,7 +42,7 @@ class HomeBloc extends Bloc { (e) => e.code == selectedLanguage, orElse: () => TotalDataEntity(), ); - if (findData.levels?.isNotEmpty ?? false) { + if (findData.nodes?.isNotEmpty ?? false) { context.goNamed(Routes.levelPage); } else { context.goNamed(Routes.downloadPage); diff --git a/lib/features/level/data/datasource/level_datasource.dart b/lib/features/level/data/datasource/level_datasource.dart index 64cdcf9..77490c1 100644 --- a/lib/features/level/data/datasource/level_datasource.dart +++ b/lib/features/level/data/datasource/level_datasource.dart @@ -2,12 +2,12 @@ import 'package:hadi_hoda_flutter/core/constants/my_constants.dart'; import 'package:hadi_hoda_flutter/core/error_handler/my_exception.dart'; import 'package:hadi_hoda_flutter/core/params/level_params.dart'; import 'package:hadi_hoda_flutter/core/utils/local_storage.dart'; -import 'package:hadi_hoda_flutter/features/level/domain/entity/level_entity.dart'; +import 'package:hadi_hoda_flutter/features/level/domain/entity/node_entity.dart'; import 'package:hadi_hoda_flutter/features/level/domain/entity/total_data_entity.dart'; import 'package:hive/hive.dart'; abstract class ILevelDatasource { - Future> getLevels({required LevelParams params}); + Future> getLevels({required LevelParams params}); } /// Local @@ -15,7 +15,7 @@ class LocalLevelDatasourceImpl implements ILevelDatasource { const LocalLevelDatasourceImpl(); @override - Future> getLevels({required LevelParams params}) async { + Future> getLevels({required LevelParams params}) async { try { final String selectedLanguage = LocalStorage.readData( key: MyConstants.selectLanguage) ?? MyConstants.defaultLanguage; @@ -24,7 +24,7 @@ class LocalLevelDatasourceImpl implements ILevelDatasource { (e) => e.code == selectedLanguage, orElse: () => TotalDataEntity(), ); - return findData.levels ?? []; + return findData.nodes ?? []; } catch (_) { throw MyException(errorMessage: 'Operation Failed'); } diff --git a/lib/features/level/data/model/node_model.dart b/lib/features/level/data/model/node_model.dart new file mode 100644 index 0000000..d476f17 --- /dev/null +++ b/lib/features/level/data/model/node_model.dart @@ -0,0 +1,25 @@ +import 'package:hadi_hoda_flutter/features/level/data/model/level_model.dart'; +import 'package:hadi_hoda_flutter/features/level/data/model/prize_model.dart'; +import 'package:hadi_hoda_flutter/features/level/domain/entity/node_entity.dart'; + +class NodeModel extends NodeEntity { + NodeModel({super.nodeType, super.level, super.prize}); + + factory NodeModel.fromJson(Map json) { + return NodeModel( + nodeType: json['node_type'] == null + ? null + : NodeType.fromJson[json['node_type']], + level: json['node_type'] == null + ? null + : json['node_type'] == 'level' + ? LevelModel.fromJson(json['data']) + : null, + prize: json['node_type'] == null + ? null + : json['node_type'] == 'prize' + ? PrizeModel.fromJson(json['data']) + : null, + ); + } +} diff --git a/lib/features/level/data/model/prize_model.dart b/lib/features/level/data/model/prize_model.dart new file mode 100644 index 0000000..7655a37 --- /dev/null +++ b/lib/features/level/data/model/prize_model.dart @@ -0,0 +1,21 @@ +import 'package:hadi_hoda_flutter/features/level/domain/entity/prize_entity.dart'; + +class PrizeModel extends PrizeEntity { + PrizeModel({ + super.id, + super.afterLevel, + super.title, + super.imageURL, + super.animationURL, + }); + + factory PrizeModel.fromJson(Map json) { + return PrizeModel( + id: json['id'], + afterLevel: json['after_level'], + title: json['title'], + imageURL: json['image_url'], + animationURL: json['animation_url'], + ); + } +} diff --git a/lib/features/level/data/repository_impl/level_repository_impl.dart b/lib/features/level/data/repository_impl/level_repository_impl.dart index 07d9366..51fdb4f 100644 --- a/lib/features/level/data/repository_impl/level_repository_impl.dart +++ b/lib/features/level/data/repository_impl/level_repository_impl.dart @@ -3,7 +3,7 @@ import 'package:hadi_hoda_flutter/core/error_handler/my_exception.dart'; import 'package:hadi_hoda_flutter/core/params/level_params.dart'; import 'package:hadi_hoda_flutter/core/utils/data_state.dart'; import 'package:hadi_hoda_flutter/features/level/data/datasource/level_datasource.dart'; -import 'package:hadi_hoda_flutter/features/level/domain/entity/level_entity.dart'; +import 'package:hadi_hoda_flutter/features/level/domain/entity/node_entity.dart'; import 'package:hadi_hoda_flutter/features/level/domain/repository/level_repository.dart'; class LevelRepositoryImpl implements ILevelRepository { @@ -12,11 +12,11 @@ class LevelRepositoryImpl implements ILevelRepository { const LevelRepositoryImpl(this.datasource); @override - Future, MyException>> getLevels({ + Future, MyException>> getLevels({ required LevelParams params, }) async { try { - final List response = await datasource.getLevels( + final List response = await datasource.getLevels( params: params, ); return DataState.success(response); diff --git a/lib/features/level/domain/entity/node_entity.dart b/lib/features/level/domain/entity/node_entity.dart new file mode 100644 index 0000000..6c9fa84 --- /dev/null +++ b/lib/features/level/domain/entity/node_entity.dart @@ -0,0 +1,30 @@ +import 'package:hadi_hoda_flutter/features/level/domain/entity/level_entity.dart'; +import 'package:hadi_hoda_flutter/features/level/domain/entity/prize_entity.dart'; +import 'package:hive/hive.dart'; + +part 'node_entity.g.dart'; + +@HiveType(typeId: 8) +enum NodeType { + @HiveField(0) + level, + @HiveField(1) + prize; + + static Map get fromJson => { + 'level': NodeType.level, + 'prize': NodeType.prize, + }; +} + +@HiveType(typeId: 7) +class NodeEntity extends HiveObject { + @HiveField(0) + NodeType? nodeType; + @HiveField(1) + LevelEntity? level; + @HiveField(2) + PrizeEntity? prize; + + NodeEntity({this.nodeType, this.level, this.prize}); +} diff --git a/lib/features/level/domain/entity/prize_entity.dart b/lib/features/level/domain/entity/prize_entity.dart new file mode 100644 index 0000000..7af133b --- /dev/null +++ b/lib/features/level/domain/entity/prize_entity.dart @@ -0,0 +1,25 @@ +import 'package:hive/hive.dart'; + +part 'prize_entity.g.dart'; + +@HiveType(typeId: 6) +class PrizeEntity extends HiveObject { + @HiveField(0) + int? id; + @HiveField(1) + int? afterLevel; + @HiveField(2) + String? title; + @HiveField(3) + String? imageURL; + @HiveField(4) + String? animationURL; + + PrizeEntity({ + this.id, + this.afterLevel, + this.title, + this.imageURL, + this.animationURL, + }); +} diff --git a/lib/features/level/domain/entity/total_data_entity.dart b/lib/features/level/domain/entity/total_data_entity.dart index 1428455..4b0c5b8 100644 --- a/lib/features/level/domain/entity/total_data_entity.dart +++ b/lib/features/level/domain/entity/total_data_entity.dart @@ -1,4 +1,4 @@ -import 'package:hadi_hoda_flutter/features/level/domain/entity/level_entity.dart'; +import 'package:hadi_hoda_flutter/features/level/domain/entity/node_entity.dart'; import 'package:hive/hive.dart'; part 'total_data_entity.g.dart'; @@ -8,10 +8,10 @@ class TotalDataEntity extends HiveObject{ @HiveField(0) String? code; @HiveField(1) - List? levels; + List? nodes; TotalDataEntity({ this.code, - this.levels, + this.nodes, }); } \ No newline at end of file diff --git a/lib/features/level/domain/entity/total_data_entity.g.dart b/lib/features/level/domain/entity/total_data_entity.g.dart index 947076d..9512c61 100644 --- a/lib/features/level/domain/entity/total_data_entity.g.dart +++ b/lib/features/level/domain/entity/total_data_entity.g.dart @@ -18,7 +18,7 @@ class TotalDataEntityAdapter extends TypeAdapter { }; return TotalDataEntity( code: fields[0] as String?, - levels: (fields[1] as List?)?.cast(), + nodes: (fields[1] as List?)?.cast(), ); } @@ -29,7 +29,7 @@ class TotalDataEntityAdapter extends TypeAdapter { ..writeByte(0) ..write(obj.code) ..writeByte(1) - ..write(obj.levels); + ..write(obj.nodes); } @override diff --git a/lib/features/level/domain/repository/level_repository.dart b/lib/features/level/domain/repository/level_repository.dart index 672d6f4..fd29b6b 100644 --- a/lib/features/level/domain/repository/level_repository.dart +++ b/lib/features/level/domain/repository/level_repository.dart @@ -1,8 +1,10 @@ import 'package:hadi_hoda_flutter/core/error_handler/my_exception.dart'; import 'package:hadi_hoda_flutter/core/params/level_params.dart'; import 'package:hadi_hoda_flutter/core/utils/data_state.dart'; -import 'package:hadi_hoda_flutter/features/level/domain/entity/level_entity.dart'; +import 'package:hadi_hoda_flutter/features/level/domain/entity/node_entity.dart'; abstract class ILevelRepository { - Future, MyException>> getLevels({required LevelParams params}); + Future, MyException>> getLevels({ + required LevelParams params, + }); } diff --git a/lib/features/level/domain/usecases/get_levels_usecase.dart b/lib/features/level/domain/usecases/get_levels_usecase.dart index 3f12106..fe555c0 100644 --- a/lib/features/level/domain/usecases/get_levels_usecase.dart +++ b/lib/features/level/domain/usecases/get_levels_usecase.dart @@ -2,16 +2,16 @@ import 'package:hadi_hoda_flutter/core/error_handler/my_exception.dart'; import 'package:hadi_hoda_flutter/core/params/level_params.dart'; import 'package:hadi_hoda_flutter/core/usecase/usecase.dart'; import 'package:hadi_hoda_flutter/core/utils/data_state.dart'; -import 'package:hadi_hoda_flutter/features/level/domain/entity/level_entity.dart'; +import 'package:hadi_hoda_flutter/features/level/domain/entity/node_entity.dart'; import 'package:hadi_hoda_flutter/features/level/domain/repository/level_repository.dart'; -class GetLevelsUseCase implements UseCase, LevelParams> { +class GetLevelsUseCase implements UseCase, LevelParams> { final ILevelRepository repository; const GetLevelsUseCase(this.repository); @override - Future, MyException>> call(LevelParams params) { + Future, MyException>> call(LevelParams params) { return repository.getLevels(params: params); } } diff --git a/lib/features/level/presentation/bloc/level_bloc.dart b/lib/features/level/presentation/bloc/level_bloc.dart index 981cc3e..62449dc 100644 --- a/lib/features/level/presentation/bloc/level_bloc.dart +++ b/lib/features/level/presentation/bloc/level_bloc.dart @@ -13,12 +13,15 @@ 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/set_platform_size.dart'; +import 'package:hadi_hoda_flutter/core/widgets/dialog/reward_dialog.dart'; import 'package:hadi_hoda_flutter/features/level/domain/entity/level_entity.dart'; import 'package:hadi_hoda_flutter/features/level/domain/entity/level_location.dart'; +import 'package:hadi_hoda_flutter/features/level/domain/entity/node_entity.dart'; +import 'package:hadi_hoda_flutter/features/level/domain/entity/prize_entity.dart'; import 'package:hadi_hoda_flutter/features/level/domain/usecases/get_levels_usecase.dart'; import 'package:hadi_hoda_flutter/features/level/presentation/bloc/level_event.dart'; import 'package:hadi_hoda_flutter/features/level/presentation/bloc/level_state.dart'; -import 'package:hadi_hoda_flutter/features/level/presentation/ui/widgets/level_widget.dart'; +import 'package:hadi_hoda_flutter/features/level/presentation/ui/widgets/node_widget.dart'; class LevelBloc extends Bloc { /// ------------constructor------------ @@ -174,7 +177,7 @@ class LevelBloc extends Bloc { ]; - final List levelList = []; + final List nodeList = []; late final Stream volumeStream; @@ -221,6 +224,14 @@ class LevelBloc extends Bloc { } } + bool getReward(int index) { + final int currentLevel = int.parse( + LocalStorage.readData(key: MyConstants.currentLevel) ?? '1', + ); + + return currentLevel > index; + } + Future changeMute() async { await Future.wait([ _mainAudioService.changeMute(), @@ -235,7 +246,15 @@ class LevelBloc extends Bloc { return currentLevel - 1; } - /// ------------Api Calls------------ + + void showReward({ + required BuildContext context, + required PrizeEntity prize, + }) { + showRewardDialog(context: context, prize: prize); + } + + /// ------------Event Calls------------ FutureOr _getLevelListEvent(GetLevelListEvent event, Emitter emit) async { final int currentLevel = int.parse( @@ -244,11 +263,11 @@ class LevelBloc extends Bloc { await _getLeveslUseCase(LevelParams()).then((value) { value.fold( (data) async { - levelList.addAll(data); + nodeList.addAll(data); try { emit(state.copyWith( getLevelStatus: const BaseComplete(''), - chooseLevel: data.singleWhere((e) => e.order == currentLevel), + chooseLevel: data.singleWhere((e) => e.level?.order == currentLevel).level, )); } catch (e) { emit(state.copyWith( diff --git a/lib/features/level/presentation/bloc/level_event.dart b/lib/features/level/presentation/bloc/level_event.dart index 818ed6f..b5824a6 100644 --- a/lib/features/level/presentation/bloc/level_event.dart +++ b/lib/features/level/presentation/bloc/level_event.dart @@ -1,5 +1,5 @@ import 'package:hadi_hoda_flutter/features/level/domain/entity/level_entity.dart'; -import 'package:hadi_hoda_flutter/features/level/presentation/ui/widgets/level_widget.dart'; +import 'package:hadi_hoda_flutter/features/level/presentation/ui/widgets/node_widget.dart'; sealed class LevelEvent { const LevelEvent(); diff --git a/lib/features/level/presentation/ui/level_page.dart b/lib/features/level/presentation/ui/level_page.dart index 2fb4ce7..1c8c075 100644 --- a/lib/features/level/presentation/ui/level_page.dart +++ b/lib/features/level/presentation/ui/level_page.dart @@ -16,7 +16,7 @@ import 'package:hadi_hoda_flutter/features/level/presentation/bloc/level_event.d import 'package:hadi_hoda_flutter/features/level/presentation/bloc/level_state.dart'; import 'package:hadi_hoda_flutter/features/level/presentation/ui/widgets/diamond_level.dart'; import 'package:hadi_hoda_flutter/features/level/presentation/ui/widgets/level_path.dart'; -import 'package:hadi_hoda_flutter/features/level/presentation/ui/widgets/level_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'; class LevelPage extends StatelessWidget { @@ -208,7 +208,7 @@ class LevelPage extends StatelessWidget { clipBehavior: Clip.none, children: [ ...List.generate( - context.read().levelList.length, + context.read().nodeList.length, (index) => Positioned( top: context.read().locationList[index].top, bottom: context.read().locationList[index].bottom, @@ -217,10 +217,17 @@ class LevelPage extends StatelessWidget { child: BlocBuilder( buildWhen: (previous, current) => previous.chooseLevel?.id != current.chooseLevel?.id, - builder: (context, state) => LevelWidget( + builder: (context, state) => NodeWidget( chooseLevel: state.chooseLevel, - level: context.read().levelList[index], - type: context.read().getLevelType(index + 1), + node: context.read().nodeList[index], + type: context.read().getLevelType, + getReward: context.read().getReward, + onRewardPressed: (prize) { + context.read().showReward( + context: context, + prize: prize, + ); + }, onTap: (LevelEntity level, LevelType type) { context.read().add( ChooseLevelEvent(level, type), diff --git a/lib/features/level/presentation/ui/widgets/level_widget.dart b/lib/features/level/presentation/ui/widgets/level_widget.dart deleted file mode 100644 index f39fc81..0000000 --- a/lib/features/level/presentation/ui/widgets/level_widget.dart +++ /dev/null @@ -1,121 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:hadi_hoda_flutter/common_ui/resources/my_assets.dart'; -import 'package:hadi_hoda_flutter/common_ui/resources/my_colors.dart'; -import 'package:hadi_hoda_flutter/common_ui/resources/my_text_style.dart'; -import 'package:hadi_hoda_flutter/core/utils/set_platform_size.dart'; -import 'package:hadi_hoda_flutter/core/widgets/images/my_image.dart'; -import 'package:hadi_hoda_flutter/features/level/domain/entity/level_entity.dart'; - -enum LevelType { - unFinished, - finished, - current; - - static Map get image => { - LevelType.unFinished: MyAssets.level, - LevelType.finished: MyAssets.finishedLevel, - LevelType.current: MyAssets.currentLevel, - }; - - static Map get textShadowColor => { - LevelType.unFinished: Color(0XFF5B5B5B), - LevelType.finished: Color(0XFF096D7B), - LevelType.current: Color(0XFF91500D), - }; - - static Map get textColor => { - LevelType.unFinished: Color(0XFFEDEDED), - LevelType.finished: Color(0XFFFFF2D0), - LevelType.current: Color(0XFFFFF2D0), - }; -} - -class LevelWidget extends StatelessWidget { - const LevelWidget({ - super.key, - required this.level, - required this.type, - required this.chooseLevel, - this.onTap, - }); - - final LevelType type; - final LevelEntity level; - final LevelEntity? chooseLevel; - final Function(LevelEntity level, LevelType type)? onTap; - - @override - Widget build(BuildContext context) { - return InkWell( - onTap: () => onTap?.call(level, type), - child: Stack( - alignment: Alignment.topCenter, - clipBehavior: Clip.none, - children: [ - MyImage( - image: LevelType.image[type] ?? MyAssets.level, - fit: BoxFit.cover, - size: setSize(context: context, tablet: 70, mobile: 44), - ), - ShaderMask( - blendMode: BlendMode.modulate, - shaderCallback: (bounds) => LinearGradient( - begin: Alignment.topCenter, - end: Alignment.bottomCenter, - colors: [ - Color(0XFFFFFFFF), - LevelType.textColor[type] ?? MyColors.white, - ], - ).createShader(bounds), - child: Text( - '${level.order ?? 0}', - maxLines: 1, - style: MYTextStyle.button1.copyWith( - fontSize: setSize(context: context, mobile: 24, tablet: 34), - shadows: [ - BoxShadow( - color: LevelType.textShadowColor[type] ?? MyColors.white, - offset: Offset(0, 2.97), - ) - ], - ), - ), - ), - if(level.id == chooseLevel?.id) - Positioned( - top: setSize(context: context, mobile: -20, tablet: -30), - child: MyImage( - image: MyAssets.location, - size: setSize(context: context,mobile: 26, tablet: 40), - ), - ), - if(type == LevelType.finished) - Positioned( - bottom: 0, - child: Container( - height: setSize(context: context, mobile: 17, tablet: 24), - width: setSize(context: context, mobile: 17, tablet: 24), - padding: EdgeInsets.all(3), - decoration: BoxDecoration( - shape: BoxShape.circle, - border: Border.all( - width: 1, - color: Color(0XFF3CFF3C), - ), - gradient: LinearGradient( - begin: Alignment.topCenter, - end: Alignment.bottomCenter, - colors: [ - Color(0XFF48D336), - Color(0XFF2D7C23), - ], - ), - ), - child: MyImage(image: MyAssets.doneRounded), - ), - ), - ], - ), - ); - } -} diff --git a/lib/features/level/presentation/ui/widgets/node_widget.dart b/lib/features/level/presentation/ui/widgets/node_widget.dart new file mode 100644 index 0000000..46af3e4 --- /dev/null +++ b/lib/features/level/presentation/ui/widgets/node_widget.dart @@ -0,0 +1,161 @@ +import 'package:flutter/material.dart'; +import 'package:hadi_hoda_flutter/common_ui/resources/my_assets.dart'; +import 'package:hadi_hoda_flutter/common_ui/resources/my_colors.dart'; +import 'package:hadi_hoda_flutter/common_ui/resources/my_text_style.dart'; +import 'package:hadi_hoda_flutter/core/utils/set_platform_size.dart'; +import 'package:hadi_hoda_flutter/core/widgets/images/my_image.dart'; +import 'package:hadi_hoda_flutter/core/widgets/inkwell/my_inkwell.dart'; +import 'package:hadi_hoda_flutter/features/level/domain/entity/level_entity.dart'; +import 'package:hadi_hoda_flutter/features/level/domain/entity/node_entity.dart'; +import 'package:hadi_hoda_flutter/features/level/domain/entity/prize_entity.dart'; + +enum LevelType { + unFinished, + finished, + current; + + static Map get image => { + LevelType.unFinished: MyAssets.level, + LevelType.finished: MyAssets.finishedLevel, + LevelType.current: MyAssets.currentLevel, + }; + + static Map get textShadowColor => { + LevelType.unFinished: Color(0XFF5B5B5B), + LevelType.finished: Color(0XFF096D7B), + LevelType.current: Color(0XFF91500D), + }; + + static Map get textColor => { + LevelType.unFinished: Color(0XFFEDEDED), + LevelType.finished: Color(0XFFFFF2D0), + LevelType.current: Color(0XFFFFF2D0), + }; +} + +class NodeWidget extends StatelessWidget { + const NodeWidget({ + super.key, + required this.node, + required this.getReward, + required this.type, + required this.chooseLevel, + this.onTap, + this.onRewardPressed, + }); + + final LevelType Function(int index) type; + final bool Function(int index) getReward; + final NodeEntity node; + final LevelEntity? chooseLevel; + final Function(LevelEntity level, LevelType type)? onTap; + final void Function(PrizeEntity prize)? onRewardPressed; + + @override + Widget build(BuildContext context) { + return Builder( + builder: (context) { + if (node.nodeType == NodeType.prize) { + return MyInkwell( + onTap: () { + if (getReward(node.prize?.afterLevel ?? 1)) { + onRewardPressed?.call(node.prize ?? PrizeEntity()); + } + }, + child: Stack( + alignment: Alignment.center, + children: [ + if (getReward(node.prize?.afterLevel ?? 1)) ...{ + MyImage(image: MyAssets.giftBackground, size: 70), + MyImage(image: MyAssets.gift, size: 50), + } else ...{ + MyImage(image: MyAssets.giftDisable, size: 50), + }, + ], + ), + ); + } else { + return InkWell( + onTap: () => onTap?.call( + node.level ?? LevelEntity(), + type(node.level?.order ?? 1), + ), + child: Stack( + alignment: Alignment.topCenter, + clipBehavior: Clip.none, + children: [ + MyImage( + image: + LevelType.image[type(node.level?.order ?? 1)] ?? + MyAssets.level, + fit: BoxFit.cover, + size: setSize(context: context, tablet: 70, mobile: 44), + ), + ShaderMask( + blendMode: BlendMode.modulate, + shaderCallback: (bounds) => LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [ + Color(0XFFFFFFFF), + LevelType.textColor[type(node.level?.order ?? 1)] ?? + MyColors.white, + ], + ).createShader(bounds), + child: Text( + '${node.level?.order ?? 0}', + maxLines: 1, + style: MYTextStyle.button1.copyWith( + fontSize: setSize( + context: context, + mobile: 24, + tablet: 34, + ), + shadows: [ + BoxShadow( + color: + LevelType.textShadowColor[type( + node.level?.order ?? 1, + )] ?? + MyColors.white, + offset: Offset(0, 2.97), + ), + ], + ), + ), + ), + if (node.level?.id == chooseLevel?.id) + Positioned( + top: setSize(context: context, mobile: -20, tablet: -30), + child: MyImage( + image: MyAssets.location, + size: setSize(context: context, mobile: 26, tablet: 40), + ), + ), + if (type(node.level?.order ?? 1) == LevelType.finished) + Positioned( + bottom: 0, + child: Container( + height: setSize(context: context, mobile: 17, tablet: 24), + width: setSize(context: context, mobile: 17, tablet: 24), + padding: EdgeInsets.all(3), + decoration: BoxDecoration( + shape: BoxShape.circle, + border: Border.all(width: 1, color: Color(0XFF3CFF3C)), + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [Color(0XFF48D336), Color(0XFF2D7C23)], + ), + ), + child: MyImage(image: MyAssets.doneRounded), + ), + ), + ], + ), + ); + } + }, + ); + } +} diff --git a/lib/features/question/data/datasource/question_datasource.dart b/lib/features/question/data/datasource/question_datasource.dart index 831f844..a89b1f3 100644 --- a/lib/features/question/data/datasource/question_datasource.dart +++ b/lib/features/question/data/datasource/question_datasource.dart @@ -3,6 +3,7 @@ import 'package:hadi_hoda_flutter/core/error_handler/my_exception.dart'; import 'package:hadi_hoda_flutter/core/params/question_params.dart'; import 'package:hadi_hoda_flutter/core/utils/local_storage.dart'; import 'package:hadi_hoda_flutter/features/level/domain/entity/level_entity.dart'; +import 'package:hadi_hoda_flutter/features/level/domain/entity/node_entity.dart'; import 'package:hadi_hoda_flutter/features/level/domain/entity/total_data_entity.dart'; import 'package:hive/hive.dart'; @@ -25,11 +26,11 @@ class QuestionDatasourceImpl implements IQuestionDatasource { (e) => e.code == selectedLanguage, orElse: () => TotalDataEntity(), ); - final LevelEntity? findLevel = findData.levels?.singleWhere( - (e) => e.id == params.id, - orElse: () => LevelEntity(), + final NodeEntity? findLevel = findData.nodes?.singleWhere( + (e) => e.level?.id == params.id, + orElse: () => NodeEntity(), ); - return findLevel ?? LevelEntity(); + return findLevel?.level ?? LevelEntity(); } catch (e) { throw MyException(errorMessage: '$e'); } @@ -47,14 +48,14 @@ class QuestionDatasourceImpl implements IQuestionDatasource { (e) => e.code == selectedLanguage, orElse: () => TotalDataEntity(), ); - if(index > (findData.levels?.length ?? 0)){ + if(index > (findData.nodes?.length ?? 0)){ throw MyException(); } - final LevelEntity? findLevel = findData.levels?.singleWhere( - (e) => e.order == index, - orElse: () => LevelEntity(), + final NodeEntity? findLevel = findData.nodes?.singleWhere( + (e) => e.level?.order == index, + orElse: () => NodeEntity(), ); - return findLevel ?? LevelEntity(); + return findLevel?.level ?? LevelEntity(); } catch (e) { throw MyException(errorMessage: '$e'); } diff --git a/lib/init_bindings.dart b/lib/init_bindings.dart index c950e18..9a80563 100644 --- a/lib/init_bindings.dart +++ b/lib/init_bindings.dart @@ -20,6 +20,8 @@ import 'package:hadi_hoda_flutter/features/guider/domain/usecases/get_first_leve import 'package:hadi_hoda_flutter/features/level/data/datasource/level_datasource.dart'; import 'package:hadi_hoda_flutter/features/level/data/repository_impl/level_repository_impl.dart'; import 'package:hadi_hoda_flutter/features/level/domain/entity/level_entity.dart'; +import 'package:hadi_hoda_flutter/features/level/domain/entity/node_entity.dart'; +import 'package:hadi_hoda_flutter/features/level/domain/entity/prize_entity.dart'; import 'package:hadi_hoda_flutter/features/level/domain/entity/total_data_entity.dart'; import 'package:hadi_hoda_flutter/features/level/domain/repository/level_repository.dart'; import 'package:hadi_hoda_flutter/features/level/domain/usecases/get_levels_usecase.dart'; @@ -92,7 +94,10 @@ Future initDataBase() async { ..registerAdapter(AnswerEntityAdapter()) ..registerAdapter(QuestionEntityAdapter()) ..registerAdapter(HadithEntityAdapter()) + ..registerAdapter(PrizeEntityAdapter()) ..registerAdapter(LevelEntityAdapter()) + ..registerAdapter(NodeTypeAdapter()) + ..registerAdapter(NodeEntityAdapter()) ..registerAdapter(TotalDataEntityAdapter()); await Hive.openBox(MyConstants.levelBox); diff --git a/lib/l10n/app_ar.arb b/lib/l10n/app_ar.arb index eac3c2f..6999f41 100644 --- a/lib/l10n/app_ar.arb +++ b/lib/l10n/app_ar.arb @@ -35,5 +35,6 @@ "showcase_notif": "سيقوم الراوي بقراءة\nالإجابات والخيارات لك.", "showcase_stepper": "هنا سترى الأسئلة الخاصة\nبهذه المرحلة للوصول\nإلى الماسة.", "showcase_hadith": "اطّلع على المصادر والأحاديث\nلهذا السؤال", - "showcase_guide": "هذا دليل سيساعدك\nفي رحلتك." + "showcase_guide": "هذا دليل سيساعدك\nفي رحلتك.", + "reward": "جائزة" } diff --git a/lib/l10n/app_de.arb b/lib/l10n/app_de.arb index 5e2cf47..156cbbd 100644 --- a/lib/l10n/app_de.arb +++ b/lib/l10n/app_de.arb @@ -35,5 +35,6 @@ "showcase_notif": "Der Sprecher wird\ndir die Antwortmöglichkeiten\nvorlesen.", "showcase_stepper": "Hier siehst du die\nFragen für diese\nStufe, um den\nDiamanten zu erreichen.", "showcase_hadith": "Quellen und\nHadithe zu dieser\nFrage ansehen.", - "showcase_guide": "Dies ist eine Anleitung,\ndie dir hilft." + "showcase_guide": "Dies ist eine Anleitung,\ndie dir hilft.", + "reward": "belohnen" } diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index cdb4691..e4b3a06 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -35,5 +35,6 @@ "showcase_notif": "The announcer will\nread the answers to\nthe options to you.", "showcase_stepper": "Here you will see the\nquestions for this\nstage to reach the\ndiamond.", "showcase_hadith": "View sources and\nhadiths for this\nquestion", - "showcase_guide": "This is a guide that will\nhelp you." + "showcase_guide": "This is a guide that will\nhelp you.", + "reward": "Reward" } \ No newline at end of file diff --git a/lib/l10n/app_fr.arb b/lib/l10n/app_fr.arb index 8c008a6..5ba2ce2 100644 --- a/lib/l10n/app_fr.arb +++ b/lib/l10n/app_fr.arb @@ -35,5 +35,6 @@ "showcase_notif": "Le narrateur lira\nles réponses des\noptions pour toi.", "showcase_stepper": "Ici, tu verras les\nquestions de cette\nétape pour atteindre\nle diamant.", "showcase_hadith": "Consulte les sources et\nles hadiths pour cette\nquestion", - "showcase_guide": "Ceci est un guide\nqui t’aidera." + "showcase_guide": "Ceci est un guide\nqui t’aidera.", + "reward": "récompense" } diff --git a/lib/l10n/app_localizations.dart b/lib/l10n/app_localizations.dart index dce9f70..68eec8f 100644 --- a/lib/l10n/app_localizations.dart +++ b/lib/l10n/app_localizations.dart @@ -321,6 +321,12 @@ abstract class AppLocalizations { /// In en, this message translates to: /// **'This is a guide that will\nhelp you.'** String get showcase_guide; + + /// No description provided for @reward. + /// + /// In en, this message translates to: + /// **'Reward'** + String get reward; } class _AppLocalizationsDelegate diff --git a/lib/l10n/app_localizations_ar.dart b/lib/l10n/app_localizations_ar.dart index fdbe46b..3c5f345 100644 --- a/lib/l10n/app_localizations_ar.dart +++ b/lib/l10n/app_localizations_ar.dart @@ -119,4 +119,7 @@ class AppLocalizationsAr extends AppLocalizations { @override String get showcase_guide => 'هذا دليل سيساعدك\nفي رحلتك.'; + + @override + String get reward => 'جائزة'; } diff --git a/lib/l10n/app_localizations_de.dart b/lib/l10n/app_localizations_de.dart index bc7873b..49f7a1f 100644 --- a/lib/l10n/app_localizations_de.dart +++ b/lib/l10n/app_localizations_de.dart @@ -126,4 +126,7 @@ class AppLocalizationsDe extends AppLocalizations { @override String get showcase_guide => 'Dies ist eine Anleitung,\ndie dir hilft.'; + + @override + String get reward => 'belohnen'; } diff --git a/lib/l10n/app_localizations_en.dart b/lib/l10n/app_localizations_en.dart index baf9d51..991362a 100644 --- a/lib/l10n/app_localizations_en.dart +++ b/lib/l10n/app_localizations_en.dart @@ -123,4 +123,7 @@ class AppLocalizationsEn extends AppLocalizations { @override String get showcase_guide => 'This is a guide that will\nhelp you.'; + + @override + String get reward => 'Reward'; } diff --git a/lib/l10n/app_localizations_fr.dart b/lib/l10n/app_localizations_fr.dart index f870a7e..6e6ec23 100644 --- a/lib/l10n/app_localizations_fr.dart +++ b/lib/l10n/app_localizations_fr.dart @@ -124,4 +124,7 @@ class AppLocalizationsFr extends AppLocalizations { @override String get showcase_guide => 'Ceci est un guide\nqui t’aidera.'; + + @override + String get reward => 'récompense'; } diff --git a/lib/l10n/app_localizations_ru.dart b/lib/l10n/app_localizations_ru.dart index dbd16a8..e374e4a 100644 --- a/lib/l10n/app_localizations_ru.dart +++ b/lib/l10n/app_localizations_ru.dart @@ -124,4 +124,7 @@ class AppLocalizationsRu extends AppLocalizations { @override String get showcase_guide => 'Это руководство,\nкоторое поможет тебе.'; + + @override + String get reward => 'награда'; } diff --git a/lib/l10n/app_localizations_tr.dart b/lib/l10n/app_localizations_tr.dart index 0ae805a..db16200 100644 --- a/lib/l10n/app_localizations_tr.dart +++ b/lib/l10n/app_localizations_tr.dart @@ -123,4 +123,7 @@ class AppLocalizationsTr extends AppLocalizations { @override String get showcase_guide => 'Bu, sana yardımcı olacak\nbir rehberdir.'; + + @override + String get reward => 'ödül'; } diff --git a/lib/l10n/app_ru.arb b/lib/l10n/app_ru.arb index c457456..9460133 100644 --- a/lib/l10n/app_ru.arb +++ b/lib/l10n/app_ru.arb @@ -35,5 +35,6 @@ "showcase_notif": "Диктор прочитает\nтебе все варианты\nответов.", "showcase_stepper": "Здесь ты увидишь\nвопросы этого этапа,\nчтобы получить\nалмаз.", "showcase_hadith": "Просмотри источники и\nхадисы по этому вопросу", - "showcase_guide": "Это руководство,\nкоторое поможет тебе." + "showcase_guide": "Это руководство,\nкоторое поможет тебе.", + "reward": "награда" } diff --git a/lib/l10n/app_tr.arb b/lib/l10n/app_tr.arb index e8b78c8..9e4691c 100644 --- a/lib/l10n/app_tr.arb +++ b/lib/l10n/app_tr.arb @@ -35,5 +35,6 @@ "showcase_notif": "Anlatıcı, seçeneklerin\ncevaplarını sana\nokuyacak.", "showcase_stepper": "Burada, elmasa ulaşmak\niçin bu aşamadaki\nsoruları göreceksin.", "showcase_hadith": "Bu soruya ait\nkaynakları ve hadisleri\nincele", - "showcase_guide": "Bu, sana yardımcı olacak\nbir rehberdir." + "showcase_guide": "Bu, sana yardımcı olacak\nbir rehberdir.", + "reward": "ödül" } diff --git a/pubspec.lock b/pubspec.lock index f14a07c..b4f8cb6 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -145,6 +145,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.4.0" + charcode: + dependency: transitive + description: + name: charcode + sha256: fb0f1107cac15a5ea6ef0a6ef71a807b9e4267c713bb93e00e92d737cc8dbd8a + url: "https://pub.dev" + source: hosted + version: "1.4.0" checked_yaml: dependency: transitive description: @@ -201,6 +209,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.6" + csslib: + dependency: transitive + description: + name: csslib + sha256: "09bad715f418841f976c77db72d5398dc1253c21fb9c0c7f0b0b985860b2d58e" + url: "https://pub.dev" + source: hosted + version: "1.0.2" dart_style: dependency: transitive description: @@ -209,6 +225,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.3.6" + dbus: + dependency: transitive + description: + name: dbus + sha256: "79e0c23480ff85dc68de79e2cd6334add97e48f7f4865d17686dd6ea81a47e8c" + url: "https://pub.dev" + source: hosted + version: "0.7.11" dio: dependency: "direct main" description: @@ -317,6 +341,14 @@ packages: description: flutter source: sdk version: "0.0.0" + freezed_annotation: + dependency: transitive + description: + name: freezed_annotation + sha256: "7294967ff0a6d98638e7acb774aac3af2550777accd8149c90af5b014e6d44d8" + url: "https://pub.dev" + source: hosted + version: "3.1.0" frontend_server_client: dependency: transitive description: @@ -325,6 +357,14 @@ packages: url: "https://pub.dev" source: hosted version: "4.0.0" + get: + dependency: transitive + description: + name: get + sha256: "5ed34a7925b85336e15d472cc4cfe7d9ebf4ab8e8b9f688585bf6b50f4c3d79a" + url: "https://pub.dev" + source: hosted + version: "4.7.3" get_it: dependency: "direct main" description: @@ -381,6 +421,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.1" + html: + dependency: transitive + description: + name: html + sha256: "6d1264f2dffa1b1101c25a91dff0dc2daee4c18e87cd8538729773c073dbf602" + url: "https://pub.dev" + source: hosted + version: "0.15.6" http: dependency: transitive description: @@ -557,6 +605,22 @@ packages: url: "https://pub.dev" source: hosted version: "2.2.0" + package_info_plus: + dependency: transitive + description: + name: package_info_plus + sha256: f69da0d3189a4b4ceaeb1a3defb0f329b3b352517f52bed4290f83d4f06bc08d + url: "https://pub.dev" + source: hosted + version: "9.0.0" + package_info_plus_platform_interface: + dependency: transitive + description: + name: package_info_plus_platform_interface + sha256: "202a487f08836a592a6bd4f901ac69b3a8f146af552bbd14407b6b41e1c3f086" + url: "https://pub.dev" + source: hosted + version: "3.2.1" path: dependency: transitive description: @@ -653,6 +717,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.8" + pod_player: + dependency: "direct main" + description: + name: pod_player + sha256: "38564f2e0d9b06fa9e4ad5023be2f6fa4cd9f95f70ace2f517a6d899b166a502" + url: "https://pub.dev" + source: hosted + version: "0.2.2" pool: dependency: transitive description: @@ -789,6 +861,14 @@ packages: url: "https://pub.dev" source: hosted version: "5.0.1" + simple_sparse_list: + dependency: transitive + description: + name: simple_sparse_list + sha256: aa648fd240fa39b49dcd11c19c266990006006de6699a412de485695910fbc1f + url: "https://pub.dev" + source: hosted + version: "0.1.4" sky_engine: dependency: transitive description: flutter @@ -898,6 +978,30 @@ packages: url: "https://pub.dev" source: hosted version: "1.4.0" + unicode: + dependency: transitive + description: + name: unicode + sha256: "0d99edbd2e74726bed2e4989713c8bec02e5581628e334d8c88c0271593fb402" + url: "https://pub.dev" + source: hosted + version: "1.1.8" + universal_html: + dependency: transitive + description: + name: universal_html + sha256: c0bcae5c733c60f26c7dfc88b10b0fd27cbcc45cb7492311cdaa6067e21c9cd4 + url: "https://pub.dev" + source: hosted + version: "2.3.0" + universal_io: + dependency: transitive + description: + name: universal_io + sha256: f63cbc48103236abf48e345e07a03ce5757ea86285ed313a6a032596ed9301e2 + url: "https://pub.dev" + source: hosted + version: "2.3.1" uuid: dependency: transitive description: @@ -938,6 +1042,46 @@ packages: url: "https://pub.dev" source: hosted version: "2.2.0" + video_player: + dependency: transitive + description: + name: video_player + sha256: "096bc28ce10d131be80dfb00c223024eb0fba301315a406728ab43dd99c45bdf" + url: "https://pub.dev" + source: hosted + version: "2.10.1" + video_player_android: + dependency: transitive + description: + name: video_player_android + sha256: d74b66f283afff135d5be0ceccca2ca74dff7df1e9b1eaca6bd4699875d3ae60 + url: "https://pub.dev" + source: hosted + version: "2.8.22" + video_player_avfoundation: + dependency: transitive + description: + name: video_player_avfoundation + sha256: e4d33b79a064498c6eb3a6a492b6a5012573d4943c28d566caf1a6c0840fe78d + url: "https://pub.dev" + source: hosted + version: "2.8.8" + video_player_platform_interface: + dependency: transitive + description: + name: video_player_platform_interface + sha256: "57c5d73173f76d801129d0531c2774052c5a7c11ccb962f1830630decd9f24ec" + url: "https://pub.dev" + source: hosted + version: "6.6.0" + video_player_web: + dependency: transitive + description: + name: video_player_web + sha256: "9f3c00be2ef9b76a95d94ac5119fb843dca6f2c69e6c9968f6f2b6c9e7afbdeb" + url: "https://pub.dev" + source: hosted + version: "2.4.0" vm_service: dependency: transitive description: @@ -946,6 +1090,22 @@ packages: url: "https://pub.dev" source: hosted version: "15.0.2" + wakelock_plus: + dependency: transitive + description: + name: wakelock_plus + sha256: "9296d40c9adbedaba95d1e704f4e0b434be446e2792948d0e4aa977048104228" + url: "https://pub.dev" + source: hosted + version: "1.4.0" + wakelock_plus_platform_interface: + dependency: transitive + description: + name: wakelock_plus_platform_interface + sha256: "036deb14cd62f558ca3b73006d52ce049fabcdcb2eddfe0bf0fe4e8a943b5cf2" + url: "https://pub.dev" + source: hosted + version: "1.3.0" watcher: dependency: transitive description: @@ -978,6 +1138,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.3" + win32: + dependency: transitive + description: + name: win32 + sha256: d7cb55e04cd34096cd3a79b3330245f54cb96a370a1c27adb3c84b917de8b08e + url: "https://pub.dev" + source: hosted + version: "5.15.0" xdg_directories: dependency: transitive description: @@ -1002,6 +1170,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.1.3" + youtube_explode_dart: + dependency: transitive + description: + name: youtube_explode_dart + sha256: "947ba05e0c4f050743e480e7bca3575ff6427d86cc898c1a69f5e1d188cdc9e0" + url: "https://pub.dev" + source: hosted + version: "2.5.3" sdks: dart: ">=3.9.2 <4.0.0" flutter: ">=3.35.0" diff --git a/pubspec.yaml b/pubspec.yaml index 98a157d..f8ba2c6 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -28,6 +28,7 @@ dependencies: lottie: ^3.3.2 path_drawing: ^1.0.1 path_provider: ^2.1.5 + pod_player: ^0.2.2 pretty_dio_logger: ^1.4.0 shared_preferences: ^2.5.3 showcaseview: ^5.0.1