Browse Source

Merge pull request 'fix/download' (#20) from fix/download into develop

Reviewed-on: https://git.nwhco.ir/amirreza.chegini/hade_hoda_flutter/pulls/20
pull/21/head
amirreza.chegini 3 weeks ago
parent
commit
10915b992e
  1. BIN
      assets/images/loading.png
  2. 0
      assets/svg/bubble_chat_left.svg
  3. 0
      assets/svg/bubble_chat_right.svg
  4. 0
      assets/svg/button.svg
  5. 0
      assets/svg/button_2.svg
  6. 0
      assets/svg/button_3.svg
  7. 0
      assets/svg/close_btn.svg
  8. 0
      assets/svg/correct.svg
  9. 0
      assets/svg/done.svg
  10. 0
      assets/svg/done_rounded.svg
  11. 0
      assets/svg/facebook.svg
  12. 0
      assets/svg/hand_point.svg
  13. 0
      assets/svg/home.svg
  14. 0
      assets/svg/instagram.svg
  15. 0
      assets/svg/lang.svg
  16. 0
      assets/svg/language.svg
  17. 0
      assets/svg/location.svg
  18. 0
      assets/svg/music.svg
  19. 0
      assets/svg/music_off.svg
  20. 0
      assets/svg/music_on.svg
  21. 0
      assets/svg/new_horizon.svg
  22. 0
      assets/svg/play.svg
  23. 0
      assets/svg/theme.svg
  24. 0
      assets/svg/unmusic.svg
  25. 0
      assets/svg/whatsapp.svg
  26. 0
      assets/svg/wrong.svg
  27. 0
      assets/svg/youtube.svg
  28. 78
      lib/common_ui/resources/my_assets.dart
  29. 4
      lib/common_ui/theme/my_theme.dart
  30. 2
      lib/core/constants/my_constants.dart
  31. 23
      lib/core/middlewares/my_middlewares.dart
  32. 12
      lib/core/routers/my_routes.dart
  33. 2
      lib/core/widgets/about_us_dialog/about_us_dialog.dart
  34. 50
      lib/core/widgets/animations/rotation_anim.dart
  35. 2
      lib/core/widgets/answer_box/styles/picture_box.dart
  36. 2
      lib/core/widgets/button/my_button.dart
  37. 4
      lib/core/widgets/confetti/my_confetti.dart
  38. 2
      lib/core/widgets/error/error_state.dart
  39. 2
      lib/core/widgets/hadith_dialog/hadith_dialog.dart
  40. 6
      lib/core/widgets/images/my_image.dart
  41. 2
      lib/core/widgets/showcase/question_showcase.dart
  42. 59
      lib/features/download/data/datasource/download_datasource.dart
  43. 16
      lib/features/download/data/repository_impl/download_repository_impl.dart
  44. 1
      lib/features/download/domain/repository/download_repository.dart
  45. 4
      lib/features/download/domain/usecases/get_images_usecase.dart
  46. 4
      lib/features/download/domain/usecases/loading_stream_usecase.dart
  47. 31
      lib/features/download/presentation/bloc/download_bloc.dart
  48. 1
      lib/features/download/presentation/bloc/download_event.dart
  49. 17
      lib/features/download/presentation/ui/download_page.dart
  50. 16
      lib/features/home/presentation/bloc/home_bloc.dart
  51. 2
      lib/features/home/presentation/ui/home_page.dart
  52. 78
      lib/features/intro/data/datasource/intro_datasource.dart
  53. 34
      lib/features/intro/data/repository_impl/intro_repository_impl.dart
  54. 9
      lib/features/intro/domain/repository/intro_repository.dart
  55. 12
      lib/features/intro/domain/usecases/loading_stream_usecase.dart
  56. 70
      lib/features/intro/presentation/bloc/intro_bloc.dart
  57. 1
      lib/features/intro/presentation/bloc/intro_event.dart
  58. 84
      lib/features/intro/presentation/ui/intro_page.dart
  59. 136
      lib/features/intro/presentation/ui/widgets/intro_loading_widget.dart
  60. 1
      lib/features/language/presentation/bloc/language_bloc.dart
  61. 2
      lib/features/language/presentation/ui/language_page.dart
  62. 14
      lib/features/level/presentation/bloc/level_bloc.dart
  63. 4
      lib/features/level/presentation/bloc/level_event.dart
  64. 37
      lib/features/level/presentation/ui/level_page.dart
  65. 22
      lib/features/level/presentation/ui/widgets/bottom_path.dart
  66. 2
      lib/features/level/presentation/ui/widgets/hint_level_widget.dart
  67. 14
      lib/features/level/presentation/ui/widgets/level_widget.dart
  68. 14
      lib/features/question/presentation/bloc/question_bloc.dart
  69. 1
      lib/features/question/presentation/ui/question_page.dart
  70. 60
      lib/features/question/presentation/ui/screens/diamond_screen.dart
  71. 44
      lib/features/question/presentation/ui/screens/question_screen.dart
  72. 2
      lib/features/question/presentation/ui/widgets/glassy_button.dart
  73. 2
      lib/features/question/presentation/ui/widgets/left_blob.dart
  74. 2
      lib/features/question/presentation/ui/widgets/question_stepper.dart
  75. 2
      lib/features/question/presentation/ui/widgets/right_blob.dart
  76. 15
      lib/init_bindings.dart
  77. 12
      pubspec.lock
  78. 6
      pubspec.yaml

BIN
assets/images/loading.png

After

Width: 156  |  Height: 174  |  Size: 8.2 KiB

0
assets/images/bubble_chat_left.svg → assets/svg/bubble_chat_left.svg

0
assets/images/bubble_chat_right.svg → assets/svg/bubble_chat_right.svg

0
assets/images/button.svg → assets/svg/button.svg

0
assets/images/button_2.svg → assets/svg/button_2.svg

0
assets/images/button_3.svg → assets/svg/button_3.svg

0
assets/images/close_btn.svg → assets/svg/close_btn.svg

0
assets/images/correct.svg → assets/svg/correct.svg

0
assets/images/done.svg → assets/svg/done.svg

0
assets/images/done_rounded.svg → assets/svg/done_rounded.svg

0
assets/images/facebook.svg → assets/svg/facebook.svg

0
assets/images/hand_point.svg → assets/svg/hand_point.svg

0
assets/images/home.svg → assets/svg/home.svg

0
assets/images/instagram.svg → assets/svg/instagram.svg

0
assets/images/lang.svg → assets/svg/lang.svg

0
assets/images/language.svg → assets/svg/language.svg

0
assets/images/location.svg → assets/svg/location.svg

0
assets/images/music.svg → assets/svg/music.svg

0
assets/images/music_off.svg → assets/svg/music_off.svg

0
assets/images/music_on.svg → assets/svg/music_on.svg

0
assets/images/new_horizon.svg → assets/svg/new_horizon.svg

0
assets/images/play.svg → assets/svg/play.svg

0
assets/images/theme.svg → assets/svg/theme.svg

0
assets/images/unmusic.svg → assets/svg/unmusic.svg

0
assets/images/whatsapp.svg → assets/svg/whatsapp.svg

0
assets/images/wrong.svg → assets/svg/wrong.svg

0
assets/images/youtube.svg → assets/svg/youtube.svg

78
lib/common_ui/resources/my_assets.dart

@ -3,47 +3,73 @@ class MyAssets {
const MyAssets._internal();
factory MyAssets() => _i;
/// PNG, JPG
static const String backgroundHome = 'assets/images/background_intro.png';
static const String closeBtn = 'assets/images/close_btn.svg';
static const String hadiHoda = 'assets/images/hadi_hoda.png';
static const String musicOff = 'assets/images/music_off.svg';
static const String musicOn = 'assets/images/music_on.svg';
static const String button = 'assets/images/button.svg';
static const String button2 = 'assets/images/button_2.svg';
static const String button3 = 'assets/images/button_3.svg';
static const String theme = 'assets/images/theme.svg';
static const String facebook = 'assets/images/facebook.svg';
static const String whatsapp = 'assets/images/whatsapp.svg';
static const String youtube = 'assets/images/youtube.svg';
static const String instagram = 'assets/images/instagram.svg';
static const String language = 'assets/images/language.svg';
static const String newHorizon = 'assets/images/new_horizon.svg';
static const String khadijeLogo = 'assets/images/khadije_logo.png';
static const String home = 'assets/images/home.svg';
static const String music = 'assets/images/music.svg';
static const String pattern = 'assets/images/pattern.png';
static const String persons = 'assets/images/persons.png';
static const String bubbleChatLeft = 'assets/images/bubble_chat_left.svg';
static const String bubbleChatRight = 'assets/images/bubble_chat_right.svg';
static const String diamond = 'assets/images/diamond.png';
static const String done = 'assets/images/done.svg';
static const String correct = 'assets/images/correct.svg';
static const String wrong = 'assets/images/wrong.svg';
static const String handPoint = 'assets/images/hand_point.svg';
static const String mapBackground = 'assets/images/map_background.png';
static const String level = 'assets/images/level.png';
static const String finishedLevel = 'assets/images/finished_level.png';
static const String currentLevel = 'assets/images/current_level.png';
static const String location = 'assets/images/location.svg';
static const String play = 'assets/images/play.svg';
static const String homeButton = 'assets/images/home_button.png';
static const String doneRounded = 'assets/images/done_rounded.svg';
static const String lang = 'assets/images/lang.svg';
static const String error = 'assets/images/error.png';
static const String leaf = 'assets/images/leaf.png';
static const String happyPersons = 'assets/images/happy_persons.png';
static const String diamondBig = 'assets/images/diamond_big.png';
static const String ship = 'assets/images/ship.png';
static const String shiny = 'assets/images/shiny.png';
static const String unMusic = 'assets/images/unmusic.svg';
static const String loading = 'assets/images/loading.png';
/// SVG
static const String closeBtn = 'assets/svg/close_btn.svg';
static const String musicOff = 'assets/svg/music_off.svg';
static const String musicOn = 'assets/svg/music_on.svg';
static const String button = 'assets/svg/button.svg';
static const String button2 = 'assets/svg/button_2.svg';
static const String button3 = 'assets/svg/button_3.svg';
static const String theme = 'assets/svg/theme.svg';
static const String facebook = 'assets/svg/facebook.svg';
static const String whatsapp = 'assets/svg/whatsapp.svg';
static const String youtube = 'assets/svg/youtube.svg';
static const String instagram = 'assets/svg/instagram.svg';
static const String language = 'assets/svg/language.svg';
static const String newHorizon = 'assets/svg/new_horizon.svg';
static const String home = 'assets/svg/home.svg';
static const String music = 'assets/svg/music.svg';
static const String bubbleChatLeft = 'assets/svg/bubble_chat_left.svg';
static const String bubbleChatRight = 'assets/svg/bubble_chat_right.svg';
static const String done = 'assets/svg/done.svg';
static const String correct = 'assets/svg/correct.svg';
static const String wrong = 'assets/svg/wrong.svg';
static const String handPoint = 'assets/svg/hand_point.svg';
static const String location = 'assets/svg/location.svg';
static const String play = 'assets/svg/play.svg';
static const String doneRounded = 'assets/svg/done_rounded.svg';
static const String lang = 'assets/svg/lang.svg';
static const String unMusic = 'assets/svg/unmusic.svg';
static final List<String> images = [
backgroundHome,
hadiHoda,
khadijeLogo,
pattern,
persons,
diamond,
mapBackground,
level,
finishedLevel,
currentLevel,
homeButton,
error,
leaf,
happyPersons,
diamondBig,
ship,
shiny,
loading,
];
}

4
lib/common_ui/theme/my_theme.dart

@ -8,9 +8,9 @@ class MyTheme {
const MyTheme._internal();
factory MyTheme() => _i;
static final ThemeData light = ThemeData(brightness: Brightness.light);
static final ThemeData light = ThemeData(brightness: Brightness.dark);
static final ThemeData dark = ThemeData(brightness: Brightness.dark);
static final ThemeData dark = ThemeData(brightness: Brightness.light);
static Map<ColorsName, Color> get lightColors => {
ColorsName.primaryColor: MyColors.white,

2
lib/core/constants/my_constants.dart

@ -11,6 +11,6 @@ class MyConstants {
static const String downloadedAudio = 'DOWNLOADED_AUDIO';
static const String extractedAudio = 'EXTRACTED_AUDIO';
static const String selectLanguage = 'SELECT_LANGUAGE';
static const String firstLanguagePage = 'FIRST_LANGUAGE_PAGE';
static const String firstDownload = 'FIRST_DOWNLOAD';
static const String currentLevel = 'CURRENT_LEVEL';
}

23
lib/core/middlewares/my_middlewares.dart

@ -0,0 +1,23 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:hadi_hoda_flutter/core/constants/my_constants.dart';
import 'package:hadi_hoda_flutter/core/routers/my_routes.dart';
import 'package:hadi_hoda_flutter/core/utils/local_storage.dart';
class MyMiddlewares {
static const MyMiddlewares _i = MyMiddlewares._internal();
const MyMiddlewares._internal();
factory MyMiddlewares() => _i;
static FutureOr<String?> intro(BuildContext context, GoRouterState state) {
final String? firstDownload = LocalStorage.readData(
key: MyConstants.firstDownload);
if (firstDownload != 'true') {
return Routes.languagePage;
} else {
return null;
}
}
}

12
lib/core/routers/my_routes.dart

@ -1,7 +1,9 @@
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:go_router/go_router.dart';
import 'package:hadi_hoda_flutter/core/middlewares/my_middlewares.dart';
import 'package:hadi_hoda_flutter/core/utils/context_provider.dart';
import 'package:hadi_hoda_flutter/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';
import 'package:hadi_hoda_flutter/features/home/presentation/bloc/home_bloc.dart';
import 'package:hadi_hoda_flutter/features/home/presentation/ui/home_page.dart';
@ -38,8 +40,9 @@ GoRouter get appPages => GoRouter(
GoRoute(
name: Routes.introPage,
path: Routes.introPage,
redirect: MyMiddlewares.intro,
builder: (context, state) => BlocProvider(
create: (context) => IntroBloc(locator(), locator()),
create: (context) => IntroBloc(),
child: const IntroPage(),
),
),
@ -47,7 +50,12 @@ GoRouter get appPages => GoRouter(
name: Routes.downloadPage,
path: Routes.downloadPage,
builder: (context, state) => BlocProvider(
create: (context) => DownloadBloc(locator(), locator(), locator()),
create: (context) => DownloadBloc(
locator(),
locator(),
locator(),
locator(),
)..add(GetImagesEvent()),
child: const DownloadPage(),
),
),

2
lib/core/widgets/about_us_dialog/about_us_dialog.dart

@ -6,9 +6,9 @@ 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/check_platform.dart';
import 'package:hadi_hoda_flutter/core/utils/my_image.dart';
import 'package:hadi_hoda_flutter/core/utils/my_localization.dart';
import 'package:hadi_hoda_flutter/core/widgets/about_us_dialog/styles/background.dart';
import 'package:hadi_hoda_flutter/core/widgets/images/my_image.dart';
Future<void> showAboutUsDialog({required BuildContext context}) async {
await showDialog(

50
lib/core/widgets/animations/rotation_anim.dart

@ -0,0 +1,50 @@
import 'package:flutter/material.dart';
class RotationAnim extends StatefulWidget {
const RotationAnim({super.key, required this.child});
final Widget child;
@override
State<RotationAnim> createState() => _RotationAnimState();
}
class _RotationAnimState extends State<RotationAnim>
with SingleTickerProviderStateMixin {
late AnimationController _controller;
late Animation<double> _animation;
@override
void initState() {
super.initState();
_controller = AnimationController(
vsync: this,
duration: Duration(seconds: 20),
);
_animation = Tween<double>(
begin: 0,
end: 20,
).animate(CurvedAnimation(parent: _controller, curve: Curves.linear));
_controller.repeat();
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return AnimatedBuilder(
animation: _controller,
child: widget.child,
builder: (context, child) => RotationTransition(
turns: _animation,
alignment: Alignment.center,
child: child,
),
);
}
}

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

@ -7,7 +7,7 @@ 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_spaces.dart';
import 'package:hadi_hoda_flutter/common_ui/resources/my_text_style.dart';
import 'package:hadi_hoda_flutter/core/utils/my_image.dart';
import 'package:hadi_hoda_flutter/core/widgets/images/my_image.dart';
import 'package:hadi_hoda_flutter/features/question/presentation/ui/widgets/black_white_effect.dart';
class AnswerPictureBox extends StatefulWidget {

2
lib/core/widgets/button/my_button.dart

@ -3,8 +3,8 @@ 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_spaces.dart';
import 'package:hadi_hoda_flutter/common_ui/resources/my_text_style.dart';
import 'package:hadi_hoda_flutter/core/utils/my_image.dart';
import 'package:hadi_hoda_flutter/core/widgets/button/enum/button_type.dart';
import 'package:hadi_hoda_flutter/core/widgets/images/my_image.dart';
class MyButton extends StatelessWidget {
const MyButton({

4
lib/core/widgets/confetti/my_confetti.dart

@ -15,9 +15,7 @@ class MyConfetti extends StatelessWidget {
shouldLoop: false,
blastDirectionality: BlastDirectionality.explosive,
blastDirection: pi / 2,
// down
gravity: 0.2,
// let pieces fall
gravity: 1,
emissionFrequency: 0.5,
numberOfParticles: 15,
particleDrag: 0.1,

2
lib/core/widgets/error/error_state.dart

@ -4,8 +4,8 @@ import 'package:hadi_hoda_flutter/common_ui/resources/my_colors.dart';
import 'package:hadi_hoda_flutter/common_ui/resources/my_spaces.dart';
import 'package:hadi_hoda_flutter/common_ui/resources/my_text_style.dart';
import 'package:hadi_hoda_flutter/core/utils/gap.dart';
import 'package:hadi_hoda_flutter/core/utils/my_image.dart';
import 'package:hadi_hoda_flutter/core/utils/my_localization.dart';
import 'package:hadi_hoda_flutter/core/widgets/images/my_image.dart';
class ErrorState extends StatelessWidget {
const ErrorState({super.key, this.onTap});

2
lib/core/widgets/hadith_dialog/hadith_dialog.dart

@ -7,8 +7,8 @@ import 'package:hadi_hoda_flutter/common_ui/resources/my_colors.dart';
import 'package:hadi_hoda_flutter/common_ui/resources/my_spaces.dart';
import 'package:hadi_hoda_flutter/common_ui/resources/my_text_style.dart';
import 'package:hadi_hoda_flutter/core/utils/check_platform.dart';
import 'package:hadi_hoda_flutter/core/utils/my_image.dart';
import 'package:hadi_hoda_flutter/core/widgets/about_us_dialog/styles/background.dart';
import 'package:hadi_hoda_flutter/core/widgets/images/my_image.dart';
Future<void> showHadithDialog({required BuildContext context}) async {
await showDialog(

6
lib/core/utils/my_image.dart → lib/core/widgets/images/my_image.dart

@ -1,5 +1,5 @@
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:vector_graphics/vector_graphics.dart';
class MyImage extends StatelessWidget {
const MyImage({
@ -25,8 +25,8 @@ class MyImage extends StatelessWidget {
height: size,
);
} else {
return SvgPicture.asset(
image,
return VectorGraphic(
loader: AssetBytesLoader(image),
fit: fit ?? BoxFit.contain,
width: size,
height: size,

2
lib/core/widgets/showcase/question_showcase.dart

@ -2,8 +2,8 @@ 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/my_image.dart';
import 'package:hadi_hoda_flutter/core/utils/screen_size.dart';
import 'package:hadi_hoda_flutter/core/widgets/images/my_image.dart';
import 'package:showcaseview/showcaseview.dart';
class QuestionShowcase extends StatelessWidget {

59
lib/features/download/data/datasource/download_datasource.dart

@ -16,6 +16,7 @@ import 'package:hadi_hoda_flutter/features/level/domain/entity/total_data_entity
import 'package:hive/hive.dart';
abstract class IDownloadDatasource {
Future<void> getImages();
Future<void> getAudios();
Future<void> saveLevels();
Stream<DownloadEntity> loadingStream();
@ -27,6 +28,54 @@ class DownloadDatasourceImpl implements IDownloadDatasource {
DownloadDatasourceImpl(this.httpRequest);
@override
Future<void> getImages() async {
final String filePath = '${StoragePath.documentDir.path}/images.zip';
if (LocalStorage.readData(key: MyConstants.downloadedImage) != 'true') {
await httpRequest.download(
urlPath: MyApi.images,
savePath: filePath,
onReceive: (count, total) {
streamController.add(DownloadEntity(
count: count / 1,
total: total / 1,
percent: (count / total) * 100,
));
},
).then((value) async {
await LocalStorage.saveData(
key: MyConstants.downloadedImage,
value: 'true',
);
});
}
try{
if (LocalStorage.readData(key: MyConstants.extractedImage) != 'true') {
final File file = File(filePath);
final Directory directory = Directory('${StoragePath.documentDir.path}/');
await ZipFile.extractToDirectory(
zipFile: file,
destinationDir: directory,
onExtracting: (zipEntry, progress) {
return ZipFileOperation.includeItem;
},
).then((value) async {
await Future.wait([
LocalStorage.saveData(
key: MyConstants.extractedImage,
value: 'true',
),
file.delete(recursive: true),
]);
});
}
} catch (e){
throw MyException(errorMessage: '$e');
}
}
@override
Future<void> getAudios() async {
final String filePath = '${StoragePath.documentDir.path}/audios.zip';
@ -52,7 +101,7 @@ class DownloadDatasourceImpl implements IDownloadDatasource {
key: MyConstants.downloadedAudio,
value: 'true',
);
},);
});
}
try{
@ -76,10 +125,6 @@ class DownloadDatasourceImpl implements IDownloadDatasource {
file.delete(recursive: true),
]);
});
} else {
streamController.add(DownloadEntity(percent: 50));
await Future.delayed(Duration(milliseconds: 150));
streamController.add(DownloadEntity(percent: 100));
}
} catch (e){
throw MyException(errorMessage: '$e');
@ -105,9 +150,7 @@ class DownloadDatasourceImpl implements IDownloadDatasource {
response?['result'],
(json) => LevelModel.fromJson(json),
);
await Future.wait([
data.add(TotalDataEntity(code: selectedLanguage, levels: levels)),
]);
await data.add(TotalDataEntity(code: selectedLanguage, levels: levels));
}
}

16
lib/features/download/data/repository_impl/download_repository_impl.dart

@ -11,6 +11,22 @@ class DownloadRepositoryImpl implements IDownloadRepository {
const DownloadRepositoryImpl(this.datasource);
@override
Future<DataState<NoParams, MyException>> getImages() async {
try {
await datasource.getImages();
return DataState.success(NoParams());
} on MyException catch (e) {
return DataState.error(e);
} catch (e) {
if (kDebugMode) {
rethrow;
} else {
return DataState.error(MyException(errorMessage: '$e'));
}
}
}
@override
Future<DataState<NoParams, MyException>> getAudios() async {
try {

1
lib/features/download/domain/repository/download_repository.dart

@ -4,6 +4,7 @@ import 'package:hadi_hoda_flutter/core/utils/data_state.dart';
import 'package:hadi_hoda_flutter/features/download/domain/entities/download_entity.dart';
abstract class IDownloadRepository {
Future<DataState<NoParams, MyException>> getImages();
Future<DataState<NoParams, MyException>> getAudios();
Future<DataState<NoParams, MyException>> saveLevels();
Stream<DownloadEntity> loadingStream();

4
lib/features/intro/domain/usecases/get_images_usecase.dart → lib/features/download/domain/usecases/get_images_usecase.dart

@ -2,10 +2,10 @@ import 'package:hadi_hoda_flutter/core/error_handler/my_exception.dart';
import 'package:hadi_hoda_flutter/core/params/no_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/intro/domain/repository/intro_repository.dart';
import 'package:hadi_hoda_flutter/features/download/domain/repository/download_repository.dart';
class GetImagesUseCase implements UseCase<NoParams, NoParams> {
final IIntroRepository repository;
final IDownloadRepository repository;
const GetImagesUseCase(this.repository);

4
lib/features/download/domain/usecases/loading_stream_audio_usecase.dart → lib/features/download/domain/usecases/loading_stream_usecase.dart

@ -1,10 +1,10 @@
import 'package:hadi_hoda_flutter/features/download/domain/entities/download_entity.dart';
import 'package:hadi_hoda_flutter/features/download/domain/repository/download_repository.dart';
class LoadingStreamAudioUseCase {
class LoadingStreamUseCase {
final IDownloadRepository repository;
const LoadingStreamAudioUseCase(this.repository);
const LoadingStreamUseCase(this.repository);
Stream<DownloadEntity> call() {
return repository.loadingStream();

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

@ -2,13 +2,16 @@ import 'dart:async';
import 'package:bloc/bloc.dart';
import 'package:go_router/go_router.dart';
import 'package:hadi_hoda_flutter/core/constants/my_constants.dart';
import 'package:hadi_hoda_flutter/core/params/no_params.dart';
import 'package:hadi_hoda_flutter/core/routers/my_routes.dart';
import 'package:hadi_hoda_flutter/core/status/base_status.dart';
import 'package:hadi_hoda_flutter/core/utils/context_provider.dart';
import 'package:hadi_hoda_flutter/core/utils/local_storage.dart';
import 'package:hadi_hoda_flutter/features/download/domain/entities/download_entity.dart';
import 'package:hadi_hoda_flutter/features/download/domain/usecases/get_audios_usecase.dart';
import 'package:hadi_hoda_flutter/features/download/domain/usecases/loading_stream_audio_usecase.dart';
import 'package:hadi_hoda_flutter/features/download/domain/usecases/get_images_usecase.dart';
import 'package:hadi_hoda_flutter/features/download/domain/usecases/loading_stream_usecase.dart';
import 'package:hadi_hoda_flutter/features/download/domain/usecases/save_levels_usecase.dart';
import 'package:hadi_hoda_flutter/features/download/presentation/bloc/download_event.dart';
import 'package:hadi_hoda_flutter/features/download/presentation/bloc/download_state.dart';
@ -16,20 +19,23 @@ import 'package:hadi_hoda_flutter/features/download/presentation/bloc/download_s
class DownloadBloc extends Bloc<DownloadEvent, DownloadState> {
/// ------------constructor------------
DownloadBloc(
this._getImagesUseCase,
this._getAudiosUseCase,
this._loadingStreamUseCase,
this._saveLevelsUseCase,
)
: super(const DownloadState()) {
on<GetImagesEvent>(_getImagesEvent);
on<GetAudiosEvent>(_getAudiosEvent);
on<SaveLevelsEvent>(_saveLevelsEvent);
loadingStream = _loadingStreamUseCase();
}
/// ------------UseCases------------
final GetImagesUseCase _getImagesUseCase;
final GetAudiosUseCase _getAudiosUseCase;
final SaveLevelsUseCase _saveLevelsUseCase;
final LoadingStreamAudioUseCase _loadingStreamUseCase;
final LoadingStreamUseCase _loadingStreamUseCase;
/// ------------Variables------------
Stream<DownloadEntity> loadingStream = Stream.empty();
@ -39,6 +45,22 @@ class DownloadBloc extends Bloc<DownloadEvent, DownloadState> {
/// ------------Functions------------
/// ------------Api Calls------------
FutureOr<void> _getImagesEvent(
GetImagesEvent event,
Emitter<DownloadState> emit,
) async {
await _getImagesUseCase(NoParams()).then((value) {
value.fold(
(data) {
add(GetAudiosEvent());
},
(error) async {
emit(state.copyWith(getFilesStatus: BaseError(error.errorMessage)));
},
);
});
}
FutureOr<void> _getAudiosEvent(
GetAudiosEvent event,
Emitter<DownloadState> emit,
@ -63,7 +85,10 @@ class DownloadBloc extends Bloc<DownloadEvent, DownloadState> {
await _saveLevelsUseCase(NoParams()).then((value) =>
value.fold(
(data) async {
ContextProvider.context.goNamed(Routes.homePage);
await LocalStorage.saveData(key: MyConstants.firstDownload, value: 'true');
if(ContextProvider.context.mounted){
ContextProvider.context.goNamed(Routes.homePage);
}
},
(error) {
emit(state.copyWith(getFilesStatus: BaseError(error.errorMessage)));

1
lib/features/download/presentation/bloc/download_event.dart

@ -1,5 +1,6 @@
sealed class DownloadEvent {
const DownloadEvent();
}
class GetImagesEvent extends DownloadEvent {}
class GetAudiosEvent extends DownloadEvent {}
class SaveLevelsEvent extends DownloadEvent {}

17
lib/features/download/presentation/ui/download_page.dart

@ -6,30 +6,19 @@ import 'package:hadi_hoda_flutter/common_ui/resources/my_spaces.dart';
import 'package:hadi_hoda_flutter/common_ui/resources/my_text_style.dart';
import 'package:hadi_hoda_flutter/core/status/base_status.dart';
import 'package:hadi_hoda_flutter/core/utils/convert_size.dart';
import 'package:hadi_hoda_flutter/core/utils/my_image.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/widgets/error/error_state.dart';
import 'package:hadi_hoda_flutter/core/widgets/images/my_image.dart';
import 'package:hadi_hoda_flutter/features/download/domain/entities/download_entity.dart';
import 'package:hadi_hoda_flutter/features/download/presentation/bloc/download_bloc.dart';
import 'package:hadi_hoda_flutter/features/download/presentation/bloc/download_event.dart';
import 'package:hadi_hoda_flutter/features/download/presentation/bloc/download_state.dart';
import 'package:hadi_hoda_flutter/features/download/presentation/ui/widgets/download_loading_widget.dart';
class DownloadPage extends StatefulWidget {
class DownloadPage extends StatelessWidget {
const DownloadPage({super.key});
@override
State<DownloadPage> createState() => _DownloadPageState();
}
class _DownloadPageState extends State<DownloadPage> {
@override
void initState() {
super.initState();
context.read<DownloadBloc>().add(GetAudiosEvent());
}
@override
Widget build(BuildContext context) {
return Scaffold(
@ -66,7 +55,7 @@ class _DownloadPageState extends State<DownloadPage> {
horizontal: 60,
),
child: ErrorState(
onTap: () => context.read<DownloadBloc>().add(GetAudiosEvent()),
onTap: () => context.read<DownloadBloc>().add(GetImagesEvent()),
),
);
} else {

16
lib/features/home/presentation/bloc/home_bloc.dart

@ -3,11 +3,15 @@ import 'dart:async';
import 'package:bloc/bloc.dart';
import 'package:flutter/cupertino.dart';
import 'package:go_router/go_router.dart';
import 'package:hadi_hoda_flutter/core/constants/my_constants.dart';
import 'package:hadi_hoda_flutter/core/routers/my_routes.dart';
import 'package:hadi_hoda_flutter/core/services/audio_service.dart';
import 'package:hadi_hoda_flutter/core/utils/local_storage.dart';
import 'package:hadi_hoda_flutter/core/widgets/about_us_dialog/about_us_dialog.dart';
import 'package:hadi_hoda_flutter/features/home/presentation/bloc/home_event.dart';
import 'package:hadi_hoda_flutter/features/home/presentation/bloc/home_state.dart';
import 'package:hadi_hoda_flutter/features/level/domain/entity/total_data_entity.dart';
import 'package:hive/hive.dart';
class HomeBloc extends Bloc<HomeEvent, HomeState> {
/// ------------constructor------------
@ -28,7 +32,17 @@ class HomeBloc extends Bloc<HomeEvent, HomeState> {
/// ------------Functions------------
void goToLevelPage(BuildContext context){
context.pushNamed(Routes.levelPage);
final String? selectedLanguage = LocalStorage.readData(key: MyConstants.selectLanguage);
final Box<TotalDataEntity> dataBox = Hive.box(MyConstants.levelBox);
final TotalDataEntity findData = dataBox.values.singleWhere(
(e) => e.code == selectedLanguage,
orElse: () => TotalDataEntity(),
);
if (findData.levels?.isNotEmpty ?? false) {
context.pushNamed(Routes.levelPage);
} else {
context.goNamed(Routes.downloadPage);
}
}
void goToLanguagePage(BuildContext context){

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

@ -2,11 +2,11 @@ import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:hadi_hoda_flutter/common_ui/resources/my_assets.dart';
import 'package:hadi_hoda_flutter/common_ui/resources/my_spaces.dart';
import 'package:hadi_hoda_flutter/core/utils/my_image.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/widgets/button/enum/button_type.dart';
import 'package:hadi_hoda_flutter/core/widgets/button/my_button.dart';
import 'package:hadi_hoda_flutter/core/widgets/images/my_image.dart';
import 'package:hadi_hoda_flutter/features/home/presentation/bloc/home_bloc.dart';
class HomePage extends StatelessWidget {

78
lib/features/intro/data/datasource/intro_datasource.dart

@ -1,78 +0,0 @@
import 'dart:async';
import 'dart:io';
import 'package:flutter_archive/flutter_archive.dart';
import 'package:hadi_hoda_flutter/core/constants/my_api.dart';
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/network/http_request.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';
abstract class IIntroDatasource {
Future<void> getImages();
Stream<DownloadEntity> loadingStream();
}
class IntroDatasourceImpl implements IIntroDatasource {
final IHttpRequest httpRequest;
final StreamController<DownloadEntity> streamController = StreamController<DownloadEntity>.broadcast();
IntroDatasourceImpl(this.httpRequest);
@override
Future<void> getImages() async {
final String filePath = '${StoragePath.documentDir.path}/images.zip';
if (LocalStorage.readData(key: MyConstants.downloadedImage) != 'true') {
await httpRequest.download(
urlPath: MyApi.images,
savePath: filePath,
onReceive: (count, total) {
streamController.add(DownloadEntity(
count: count / 1,
total: total / 1,
percent: (count / total) * 100,
));
},
).then((value) async {
await LocalStorage.saveData(
key: MyConstants.downloadedImage,
value: 'true',
);
});
}
try{
if (LocalStorage.readData(key: MyConstants.extractedImage) != 'true') {
final File file = File(filePath);
final Directory directory = Directory('${StoragePath.documentDir.path}/');
await ZipFile.extractToDirectory(
zipFile: file,
destinationDir: directory,
onExtracting: (zipEntry, progress) {
return ZipFileOperation.includeItem;
},
).then((value) async {
await Future.wait([
LocalStorage.saveData(
key: MyConstants.extractedImage,
value: 'true',
),
file.delete(recursive: true),
]);
});
} else {
streamController.add(DownloadEntity(percent: 50));
await Future.delayed(Duration(milliseconds: 150));
streamController.add(DownloadEntity(percent: 100));
}
} catch (e){
throw MyException(errorMessage: '$e');
}
}
@override
Stream<DownloadEntity> loadingStream() => streamController.stream;
}

34
lib/features/intro/data/repository_impl/intro_repository_impl.dart

@ -1,34 +0,0 @@
import 'package:flutter/foundation.dart';
import 'package:hadi_hoda_flutter/core/error_handler/my_exception.dart';
import 'package:hadi_hoda_flutter/core/params/no_params.dart';
import 'package:hadi_hoda_flutter/core/utils/data_state.dart';
import 'package:hadi_hoda_flutter/features/download/domain/entities/download_entity.dart';
import 'package:hadi_hoda_flutter/features/intro/data/datasource/intro_datasource.dart';
import 'package:hadi_hoda_flutter/features/intro/domain/repository/intro_repository.dart';
class IntroRepositoryImpl implements IIntroRepository {
final IIntroDatasource datasource;
const IntroRepositoryImpl(this.datasource);
@override
Future<DataState<NoParams, MyException>> getImages() async {
try {
await datasource.getImages();
return DataState.success(NoParams());
} on MyException catch (e) {
return DataState.error(e);
} catch (e) {
if (kDebugMode) {
rethrow;
} else {
return DataState.error(MyException(errorMessage: '$e'));
}
}
}
@override
Stream<DownloadEntity> loadingStream() {
return datasource.loadingStream();
}
}

9
lib/features/intro/domain/repository/intro_repository.dart

@ -1,9 +0,0 @@
import 'package:hadi_hoda_flutter/core/error_handler/my_exception.dart';
import 'package:hadi_hoda_flutter/core/params/no_params.dart';
import 'package:hadi_hoda_flutter/core/utils/data_state.dart';
import 'package:hadi_hoda_flutter/features/download/domain/entities/download_entity.dart';
abstract class IIntroRepository {
Future<DataState<NoParams, MyException>> getImages();
Stream<DownloadEntity> loadingStream();
}

12
lib/features/intro/domain/usecases/loading_stream_usecase.dart

@ -1,12 +0,0 @@
import 'package:hadi_hoda_flutter/features/download/domain/entities/download_entity.dart';
import 'package:hadi_hoda_flutter/features/intro/domain/repository/intro_repository.dart';
class LoadingStreamUseCase {
final IIntroRepository repository;
const LoadingStreamUseCase(this.repository);
Stream<DownloadEntity> call() {
return repository.loadingStream();
}
}

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

@ -1,64 +1,44 @@
import 'dart:async';
import 'package:bloc/bloc.dart';
import 'package:flutter/cupertino.dart';
import 'package:go_router/go_router.dart';
import 'package:hadi_hoda_flutter/core/constants/my_constants.dart';
import 'package:hadi_hoda_flutter/core/params/no_params.dart';
import 'package:hadi_hoda_flutter/common_ui/resources/my_assets.dart';
import 'package:hadi_hoda_flutter/core/routers/my_routes.dart';
import 'package:hadi_hoda_flutter/core/status/base_status.dart';
import 'package:hadi_hoda_flutter/core/utils/context_provider.dart';
import 'package:hadi_hoda_flutter/core/utils/local_storage.dart';
import 'package:hadi_hoda_flutter/features/download/domain/entities/download_entity.dart';
import 'package:hadi_hoda_flutter/features/intro/domain/usecases/get_images_usecase.dart';
import 'package:hadi_hoda_flutter/features/intro/domain/usecases/loading_stream_usecase.dart';
import 'package:hadi_hoda_flutter/features/intro/presentation/bloc/intro_event.dart';
import 'package:hadi_hoda_flutter/features/intro/presentation/bloc/intro_state.dart';
class IntroBloc extends Bloc<IntroEvent, IntroState> {
/// ------------constructor------------
IntroBloc(
this._getImagesUseCase,
this._loadingStreamUseCase,
)
: super(const IntroState()) {
on<GetImagesEvent>(_getImagesEvent);
loadingStream = _loadingStreamUseCase();
}
IntroBloc() : super(const IntroState());
/// ------------UseCases------------
final GetImagesUseCase _getImagesUseCase;
final LoadingStreamUseCase _loadingStreamUseCase;
/// ------------Variables------------
Stream<DownloadEntity> loadingStream = Stream.empty();
/// ------------Controllers------------
/// ------------Functions------------
Future<void> _precacheAllImages(BuildContext context) async {
await Future.wait(
MyAssets.images.map(
(assetPath) => precacheImage(AssetImage(assetPath), context),
),
);
}
/// ------------Api Calls------------
FutureOr<void> _getImagesEvent(
GetImagesEvent event,
Emitter<IntroState> emit,
) async {
emit(state.copyWith(getFilesStatus: BaseInit()));
await _getImagesUseCase(NoParams()).then((value) {
value.fold(
(data) async {
if(LocalStorage.readData(key: MyConstants.firstLanguagePage) != 'true'){
ContextProvider.context.goNamed(Routes.languagePage);
} else {
await Future.delayed(Duration(milliseconds: 500), () {
if (ContextProvider.context.mounted) {
ContextProvider.context.goNamed(Routes.homePage);
}
});
}
},
(error) async {
emit(state.copyWith(getFilesStatus: BaseError(error.errorMessage)));
},
);
});
Future<void> goToHomePage(BuildContext context) async {
if (context.mounted) {
await _precacheAllImages(context);
}
await Future.delayed(
Duration(seconds: 2),
() {
if (context.mounted) {
context.goNamed(Routes.homePage);
}
},
);
}
/// ------------Api Calls------------
}

1
lib/features/intro/presentation/bloc/intro_event.dart

@ -1,4 +1,3 @@
sealed class IntroEvent {
const IntroEvent();
}
class GetImagesEvent extends IntroEvent {}

84
lib/features/intro/presentation/ui/intro_page.dart

@ -1,20 +1,11 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.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_spaces.dart';
import 'package:hadi_hoda_flutter/common_ui/resources/my_text_style.dart';
import 'package:hadi_hoda_flutter/core/status/base_status.dart';
import 'package:hadi_hoda_flutter/core/utils/convert_size.dart';
import 'package:hadi_hoda_flutter/core/utils/my_image.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/widgets/error/error_state.dart';
import 'package:hadi_hoda_flutter/features/download/domain/entities/download_entity.dart';
import 'package:hadi_hoda_flutter/core/widgets/animations/rotation_anim.dart';
import 'package:hadi_hoda_flutter/core/widgets/images/my_image.dart';
import 'package:hadi_hoda_flutter/features/intro/presentation/bloc/intro_bloc.dart';
import 'package:hadi_hoda_flutter/features/intro/presentation/bloc/intro_event.dart';
import 'package:hadi_hoda_flutter/features/intro/presentation/bloc/intro_state.dart';
import 'package:hadi_hoda_flutter/features/intro/presentation/ui/widgets/intro_loading_widget.dart';
class IntroPage extends StatefulWidget {
const IntroPage({super.key});
@ -27,9 +18,12 @@ class _IntroPageState extends State<IntroPage> {
@override
void initState() {
super.initState();
context.read<IntroBloc>().add(GetImagesEvent());
WidgetsBinding.instance.addPostFrameCallback((_) {
context.read<IntroBloc>().goToHomePage(context);
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
@ -55,31 +49,12 @@ class _IntroPageState extends State<IntroPage> {
),
),
),
child: BlocBuilder<IntroBloc, IntroState>(
buildWhen: (previous, current) =>
previous.getFilesStatus != current.getFilesStatus,
builder: (context, state) {
if (state.getFilesStatus is BaseError) {
return Padding(
padding: EdgeInsets.symmetric(
vertical: MediaQuery.viewPaddingOf(context).bottom + MySpaces.s16,
horizontal: 60,
),
child: ErrorState(
onTap: () => context.read<IntroBloc>().add(GetImagesEvent()),
),
);
} else {
return Stack(
alignment: Alignment.center,
children: [
_image(),
_text(context),
_loading(context),
],
);
}
}
child: Stack(
alignment: Alignment.center,
children: [
_image(),
_loading(context),
],
),
),
);
@ -92,39 +67,16 @@ class _IntroPageState extends State<IntroPage> {
);
}
Widget _text(BuildContext context) {
return PositionedDirectional(
bottom: 130,
child: Column(
spacing: MySpaces.s6,
children: [
Text(
context.translate.please_wait,
style: Marhey.medium22.copyWith(
color: MyColors.white,
),
),
StreamBuilder<DownloadEntity>(
initialData: DownloadEntity(),
stream: context.read<IntroBloc>().loadingStream,
builder: (context, snapshot) => Text(
'${context.translate.downloading_data} (${snapshot.data?.count.toMB ?? 0.0}mb / ${snapshot.data?.total.toMB ?? 0.0}mb)',
style: Marhey.medium12.copyWith(
color: MyColors.white,
),
),
),
],
),
);
}
Positioned _loading(BuildContext context) {
return Positioned(
bottom: MediaQuery.viewPaddingOf(context).bottom + MySpaces.s16,
child: IntroLoadingWidget(
loadingStream: context.read<IntroBloc>().loadingStream,
),
child: RotationAnim(
child: MyImage(
image: MyAssets.loading,
size: 70,
),
)
);
}
}

136
lib/features/intro/presentation/ui/widgets/intro_loading_widget.dart

@ -1,136 +0,0 @@
import 'package:flutter/material.dart';
import 'package:hadi_hoda_flutter/common_ui/resources/my_spaces.dart';
import 'package:hadi_hoda_flutter/common_ui/resources/my_text_style.dart';
import 'package:hadi_hoda_flutter/features/download/domain/entities/download_entity.dart';
class IntroLoadingWidget extends StatelessWidget {
const IntroLoadingWidget({
super.key,
this.loadingStream,
});
final Stream<DownloadEntity>? loadingStream;
@override
Widget build(BuildContext context) {
return ClipPath(
clipper: BubbleClip(),
child: Container(
width: 300,
height: 60,
padding: EdgeInsets.symmetric(
vertical: MySpaces.s4,
horizontal: MySpaces.s2,
),
decoration: const BoxDecoration(
gradient: LinearGradient(
begin: Alignment(0, 1), // bottom
end: Alignment(0, -1), // top
colors: [
Color(0xFFCADCFF), // #CADCFF
Colors.white, // #FFFFFF
],
),
),
child: StreamBuilder<DownloadEntity>(
initialData: DownloadEntity(),
stream: loadingStream,
builder: (context, snapshot) {
return Row(
children: [
Expanded(
flex: 85,
child: ClipPath(
clipper: BubbleClip(),
child: AnimatedContainer(
duration: const Duration(milliseconds: 300),
padding: EdgeInsetsDirectional.only(
end: 260 - ((snapshot.data?.percent ?? 0) * 260 / 100),
),
decoration: BoxDecoration(
color: Color(0xFF1F59BD).withValues(alpha: 0.25),
),
child: ClipPath(
clipper: BubbleClip(),
child: Container(
decoration: BoxDecoration(
gradient: RadialGradient(
radius: 2,
colors: [
Color(0xFFFFBD00), // #CADCFF
Color(0xFFFF772C), // #CADCFF
],
),
),
),
),
),
),
),
Expanded(
flex: 15,
child: Center(
child: Text(
'${snapshot.data?.percent?.toInt() ?? 0}%',
style: DinoKids.regular17.copyWith(
color: Color(0XFF6E83A8),
),
),
),
),
],
);
}
),
),
);
}
}
class BubbleClip extends CustomClipper<Path> {
@override
Path getClip(Size size) {
// Original SVG viewBox: 334 x 60
const double w0 = 334.0;
const double h0 = 60.0;
final sx = size.width / w0;
final sy = size.height / h0;
// SVG path:
// M9.82057 10.3597
// C -1.70838 17.1589 -3.47995 44.4301 6.60447 53.1719
// C 16.0075 61.291 305.076 61.9385 323.201 53.4956
// C 341.326 45.0527 332.116 8.04571 324.829 5.7273
// C 307.985 -2.06805 28.6539 -0.77294 9.82057 10.3597
// Z
final p = Path()
..moveTo(9.82057 * sx, 10.3597 * sy)
..cubicTo(
-1.70838 * sx, 17.1589 * sy,
-3.47995 * sx, 44.4301 * sy,
6.60447 * sx, 53.1719 * sy,
)
..cubicTo(
16.0075 * sx, 61.291 * sy,
305.076 * sx, 61.9385 * sy,
323.201 * sx, 53.4956 * sy,
)
..cubicTo(
341.326 * sx, 45.0527 * sy,
332.116 * sx, 8.04571 * sy,
324.829 * sx, 5.7273 * sy,
)
..cubicTo(
307.985 * sx, -2.06805 * sy,
28.6539 * sx, -0.77294 * sy,
9.82057 * sx, 10.3597 * sy,
)
..close();
return p;
}
@override
bool shouldReclip(covariant CustomClipper<Path> oldClipper) => false;
}

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

@ -49,7 +49,6 @@ class LanguageBloc extends Bloc<LanguageEvent, LanguageState> {
key: MyConstants.selectLanguage,
value: state.selectedLang.code ?? 'fa',
),
LocalStorage.saveData(key: MyConstants.firstLanguagePage, value: 'true')
]);
if (Directory(

2
lib/features/language/presentation/ui/language_page.dart

@ -4,10 +4,10 @@ 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_spaces.dart';
import 'package:hadi_hoda_flutter/common_ui/resources/my_text_style.dart';
import 'package:hadi_hoda_flutter/core/utils/my_image.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/widgets/button/my_button.dart';
import 'package:hadi_hoda_flutter/core/widgets/images/my_image.dart';
import 'package:hadi_hoda_flutter/features/language/presentation/bloc/language_bloc.dart';
import 'package:hadi_hoda_flutter/features/language/presentation/bloc/language_event.dart';
import 'package:hadi_hoda_flutter/features/language/presentation/bloc/language_state.dart';

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

@ -26,6 +26,7 @@ class LevelBloc extends Bloc<LevelEvent, LevelState> {
on<GetLevelListEvent>(_getLevelListEvent);
on<SetCurrentLevelEvent>(_setCurrentLevelEvent);
on<StartScrollEvent>(_startScrollEvent);
on<ChooseLevelEvent>(_chooseLevelEvent);
}
@override
@ -39,11 +40,11 @@ class LevelBloc extends Bloc<LevelEvent, LevelState> {
/// ------------Variables------------
final List<LevelLocation> bottomLocationList = [
LevelLocation(bottom: -30, left: 30, index: 1),
LevelLocation(bottom: -20, left: 30, index: 1),
LevelLocation(bottom: 50, left: 100, index: 2),
LevelLocation(bottom: 150, left: 60, index: 3),
LevelLocation(bottom: 210, left: 110, index: 4),
LevelLocation(bottom: 250, right: 60, index: 5),
LevelLocation(bottom: 260, right: 70, index: 5),
LevelLocation(top: 170, right: 40, index: 6),
LevelLocation(top: 70, right: 70, index: 7),
LevelLocation(top: -20, right: 70, index: 8),
@ -148,7 +149,7 @@ class LevelBloc extends Bloc<LevelEvent, LevelState> {
await Future.delayed(const Duration(seconds: 1));
if (scrollController.hasClients) {
if(currentLevel < 9){
if(currentLevel > 14){
scrollController.animateTo(
scrollController.position.maxScrollExtent,
duration: const Duration(milliseconds: 500), // Note: 500 seconds is very long.
@ -173,4 +174,11 @@ class LevelBloc extends Bloc<LevelEvent, LevelState> {
}
add(GetLevelListEvent());
}
FutureOr<void> _chooseLevelEvent(ChooseLevelEvent event,
Emitter<LevelState> emit,) {
if (event.type != LevelType.unFinished) {
emit(state.copyWith(chooseLevel: event.level));
}
}
}

4
lib/features/level/presentation/bloc/level_event.dart

@ -1,4 +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';
sealed class LevelEvent {
const LevelEvent();
@ -9,5 +10,6 @@ class StartScrollEvent extends LevelEvent {}
class SetCurrentLevelEvent extends LevelEvent {}
class ChooseLevelEvent extends LevelEvent {
final LevelEntity level;
const ChooseLevelEvent(this.level);
final LevelType type;
const ChooseLevelEvent(this.level, this.type);
}

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

@ -2,10 +2,11 @@ import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:hadi_hoda_flutter/common_ui/resources/my_assets.dart';
import 'package:hadi_hoda_flutter/common_ui/resources/my_spaces.dart';
import 'package:hadi_hoda_flutter/core/utils/my_image.dart';
import 'package:hadi_hoda_flutter/core/utils/screen_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';
import 'package:hadi_hoda_flutter/features/level/presentation/bloc/level_bloc.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/bottom_path.dart';
import 'package:hadi_hoda_flutter/features/level/presentation/ui/widgets/hint_level_widget.dart';
@ -22,6 +23,7 @@ class LevelPage extends StatelessWidget {
children: [
SingleChildScrollView(
controller: context.read<LevelBloc>().scrollController,
reverse: true,
child: Stack(
alignment: Alignment.center,
children: [
@ -112,10 +114,15 @@ class LevelPage extends StatelessWidget {
bottom: context.read<LevelBloc>().topLocationList[index].bottom,
right: context.read<LevelBloc>().topLocationList[index].right,
left: context.read<LevelBloc>().topLocationList[index].left,
child: LevelWidget(
level: context.read<LevelBloc>().top12LevelList[index],
type: context.read<LevelBloc>().getLevelType(index + 9),
onTap: (LevelEntity level) {},
child: BlocBuilder<LevelBloc, LevelState>(
builder: (context, state) => LevelWidget(
chooseLevel: state.chooseLevel,
level: context.read<LevelBloc>().top12LevelList[index],
type: context.read<LevelBloc>().getLevelType(index + 9),
onTap: (LevelEntity level, LevelType type) {
context.read<LevelBloc>().add(ChooseLevelEvent(level, type));
},
),
),
),
),
@ -133,10 +140,7 @@ class LevelPage extends StatelessWidget {
builder: (context, state) => Stack(
clipBehavior: Clip.none,
children: [
BottomPath(
width: context.widthScreen * 0.75,
height: context.heightScreen * 0.65,
),
BottomPath(),
...List.generate(
context.read<LevelBloc>().bottom8LevelList.length,
(index) => Positioned(
@ -144,10 +148,17 @@ class LevelPage extends StatelessWidget {
bottom: context.read<LevelBloc>().bottomLocationList[index].bottom,
right: context.read<LevelBloc>().bottomLocationList[index].right,
left: context.read<LevelBloc>().bottomLocationList[index].left,
child: LevelWidget(
level: context.read<LevelBloc>().bottom8LevelList[index],
type: context.read<LevelBloc>().getLevelType(index + 1),
onTap: (LevelEntity level) {},
child: BlocBuilder<LevelBloc, LevelState>(
buildWhen: (previous, current) =>
previous.chooseLevel?.id != current.chooseLevel?.id,
builder: (context, state) => LevelWidget(
chooseLevel: state.chooseLevel,
level: context.read<LevelBloc>().bottom8LevelList[index],
type: context.read<LevelBloc>().getLevelType(index + 1),
onTap: (LevelEntity level, LevelType type) {
context.read<LevelBloc>().add(ChooseLevelEvent(level, type));
},
),
),
),
),

22
lib/features/level/presentation/ui/widgets/bottom_path.dart

@ -1,34 +1,28 @@
import 'package:flutter/material.dart';
import 'package:hadi_hoda_flutter/common_ui/resources/my_colors.dart';
import 'package:hadi_hoda_flutter/core/utils/screen_size.dart';
import 'package:path_drawing/path_drawing.dart';
class BottomPath extends StatelessWidget {
const BottomPath({
super.key,
this.width = 500,
this.height = 1523,
this.color = Colors.white,
});
const BottomPath({super.key});
final double width;
final double height;
final Color color;
@override
Widget build(BuildContext context) {
return CustomPaint(
painter: _Path(color),
painter: _Path(),
size: Size(
width,
height,
context.widthScreen * 0.76,
context.heightScreen * 0.64,
), // or Size.infinite inside a parent with constraints
);
}
}
class _Path extends CustomPainter {
_Path(this.color);
const _Path();
final Color color;
final Color color = MyColors.white;
// SVG viewBox
static const double _vbW = 500;

2
lib/features/level/presentation/ui/widgets/hint_level_widget.dart

@ -2,10 +2,10 @@ 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_spaces.dart';
import 'package:hadi_hoda_flutter/common_ui/resources/my_text_style.dart';
import 'package:hadi_hoda_flutter/core/utils/my_image.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/widgets/answer_box/styles/text_box.dart';
import 'package:hadi_hoda_flutter/core/widgets/images/my_image.dart';
import 'package:hadi_hoda_flutter/features/level/domain/entity/level_entity.dart';
class HintLevelWidget extends StatelessWidget {

14
lib/features/level/presentation/ui/widgets/level_widget.dart

@ -2,7 +2,7 @@ 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/my_image.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 {
@ -21,18 +21,20 @@ class LevelWidget extends StatelessWidget {
const LevelWidget({
super.key,
required this.level,
this.type,
required this.type,
required this.chooseLevel,
this.onTap,
});
final LevelType? type;
final LevelType type;
final LevelEntity level;
final Function(LevelEntity level)? onTap;
final LevelEntity? chooseLevel;
final Function(LevelEntity level, LevelType type)? onTap;
@override
Widget build(BuildContext context) {
return InkWell(
onTap: () => onTap?.call(level),
onTap: () => onTap?.call(level, type),
child: Stack(
alignment: Alignment.topCenter,
clipBehavior: Clip.none,
@ -51,7 +53,7 @@ class LevelWidget extends StatelessWidget {
],
),
),
if(type == LevelType.current)
if(level.id == chooseLevel?.id)
Positioned(
top: -20,
child: MyImage(

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

@ -126,13 +126,15 @@ class QuestionBloc extends Bloc<QuestionEvent, QuestionState> {
);
if (state.currentQuestion?.order ==
state.levelEntity?.questions?.length) {
int currentLevel = int.parse(
int currentLevel = int.parse(
LocalStorage.readData(key: MyConstants.currentLevel) ?? '1');
++currentLevel;
await LocalStorage.saveData(
key: MyConstants.currentLevel,
value: '$currentLevel',
);
if (state.levelEntity?.order == currentLevel) {
++currentLevel;
await LocalStorage.saveData(
key: MyConstants.currentLevel,
value: '$currentLevel',
);
}
} else {
await playVoice();
}

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

@ -44,6 +44,7 @@ class QuestionPage extends StatelessWidget {
),
),
child: SafeArea(
bottom: false,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: MySpaces.s16),
child: Column(

60
lib/features/question/presentation/ui/screens/diamond_screen.dart

@ -4,13 +4,14 @@ import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.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_spaces.dart';
import 'package:hadi_hoda_flutter/common_ui/resources/my_text_style.dart';
import 'package:hadi_hoda_flutter/core/utils/gap.dart';
import 'package:hadi_hoda_flutter/core/utils/my_image.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/widgets/button/enum/button_type.dart';
import 'package:hadi_hoda_flutter/core/widgets/button/my_button.dart';
import 'package:hadi_hoda_flutter/core/widgets/images/my_image.dart';
import 'package:hadi_hoda_flutter/features/question/presentation/bloc/question_bloc.dart';
import 'package:hadi_hoda_flutter/features/question/presentation/bloc/question_event.dart';
@ -128,37 +129,42 @@ class DiamondScreen extends StatelessWidget {
);
}
Row _btns(BuildContext context) {
return Row(
children: [
Expanded(
child: InkWell(
onTap: () => context.read<QuestionBloc>().goToLevelPage(context: context),
child: Stack(
alignment: Alignment.center,
children: [
MyImage(image: MyAssets.button3, size: 84),
Positioned(
top: 10,
child: Text(
context.translate.view_map,
style: DinoKids.regular35.copyWith(
color: Color(0XFFD93D16),
Widget _btns(BuildContext context) {
return Padding(
padding: EdgeInsets.only(
bottom: MediaQuery.viewPaddingOf(context).bottom + MySpaces.s16,
),
child: Row(
children: [
Expanded(
child: InkWell(
onTap: () => context.read<QuestionBloc>().goToLevelPage(context: context),
child: Stack(
alignment: Alignment.center,
children: [
MyImage(image: MyAssets.button3, size: 84),
Positioned(
top: 10,
child: Text(
context.translate.view_map,
style: DinoKids.regular35.copyWith(
color: Color(0XFFD93D16),
),
),
),
),
],
],
),
),
),
),
Expanded(
child: MyButton(
onTap: () => context.read<QuestionBloc>().add(GetNextLevelEvent()),
title: context.translate.go_next,
type: ButtonType.type2,
Expanded(
child: MyButton(
onTap: () => context.read<QuestionBloc>().add(GetNextLevelEvent()),
title: context.translate.go_next,
type: ButtonType.type2,
),
),
),
],
],
),
);
}
}

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

@ -5,9 +5,9 @@ import 'package:hadi_hoda_flutter/common_ui/resources/my_colors.dart';
import 'package:hadi_hoda_flutter/common_ui/resources/my_spaces.dart';
import 'package:hadi_hoda_flutter/common_ui/resources/my_text_style.dart';
import 'package:hadi_hoda_flutter/core/utils/gap.dart';
import 'package:hadi_hoda_flutter/core/utils/my_image.dart';
import 'package:hadi_hoda_flutter/core/utils/my_localization.dart';
import 'package:hadi_hoda_flutter/core/widgets/answer_box/answer_box.dart';
import 'package:hadi_hoda_flutter/core/widgets/images/my_image.dart';
import 'package:hadi_hoda_flutter/core/widgets/showcase/question_showcase.dart';
import 'package:hadi_hoda_flutter/features/question/domain/entity/answer_entity.dart';
import 'package:hadi_hoda_flutter/features/question/presentation/bloc/question_bloc.dart';
@ -116,25 +116,39 @@ class QuestionScreen extends StatelessWidget {
builder: (context, state) => Stack(
clipBehavior: Clip.none,
children: [
if(state.correctAnswer == false)
PositionedDirectional(
start: -100,
top: -10,
PositionedDirectional(
start: -100,
top: -10,
child: AnimatedOpacity(
opacity: state.correctAnswer == false ? 1 : 0,
duration: Duration(milliseconds: 200),
child: LeftBlob(),
),
MyImage(
image: state.correctAnswer == true
? MyAssets.happyPersons
: MyAssets.persons,
fit: BoxFit.contain,
size: 110,
),
if(state.correctAnswer == false)
PositionedDirectional(
top: -30,
end: -90,
AnimatedCrossFade(
duration: Duration(milliseconds: 200),
reverseDuration: Duration(milliseconds: 200),
crossFadeState: state.correctAnswer == true ? CrossFadeState
.showSecond : CrossFadeState.showFirst,
firstChild: MyImage(
image: MyAssets.persons,
fit: BoxFit.contain,
),
secondChild: MyImage(
image: MyAssets.happyPersons,
fit: BoxFit.contain,
size: 110,
),
),
PositionedDirectional(
top: -30,
end: -90,
child: AnimatedOpacity(
opacity: state.correctAnswer == false ? 1 : 0,
duration: Duration(milliseconds: 200),
child: RightBlob(),
),
),
],
),
),

2
lib/features/question/presentation/ui/widgets/glassy_button.dart

@ -1,6 +1,6 @@
import 'package:flutter/material.dart';
import 'package:hadi_hoda_flutter/common_ui/resources/my_spaces.dart';
import 'package:hadi_hoda_flutter/core/utils/my_image.dart';
import 'package:hadi_hoda_flutter/core/widgets/images/my_image.dart';
class GlassyButton extends StatelessWidget {
const GlassyButton({super.key, required this.image, this.onTap});

2
lib/features/question/presentation/ui/widgets/left_blob.dart

@ -1,8 +1,8 @@
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_text_style.dart';
import 'package:hadi_hoda_flutter/core/utils/my_image.dart';
import 'package:hadi_hoda_flutter/core/utils/my_localization.dart';
import 'package:hadi_hoda_flutter/core/widgets/images/my_image.dart';
class LeftBlob extends StatelessWidget {
const LeftBlob({super.key});

2
lib/features/question/presentation/ui/widgets/question_stepper.dart

@ -1,7 +1,7 @@
import 'package:easy_stepper/easy_stepper.dart';
import 'package:flutter/material.dart';
import 'package:hadi_hoda_flutter/common_ui/resources/my_assets.dart';
import 'package:hadi_hoda_flutter/core/utils/my_image.dart';
import 'package:hadi_hoda_flutter/core/widgets/images/my_image.dart';
class QuestionStepper extends StatelessWidget {
const QuestionStepper({super.key, required this.length ,required this.currentStep});

2
lib/features/question/presentation/ui/widgets/right_blob.dart

@ -1,8 +1,8 @@
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_text_style.dart';
import 'package:hadi_hoda_flutter/core/utils/my_image.dart';
import 'package:hadi_hoda_flutter/core/utils/my_localization.dart';
import 'package:hadi_hoda_flutter/core/widgets/images/my_image.dart';
class RightBlob extends StatelessWidget {
const RightBlob({super.key});

15
lib/init_bindings.dart

@ -9,13 +9,9 @@ import 'package:hadi_hoda_flutter/features/download/data/datasource/download_dat
import 'package:hadi_hoda_flutter/features/download/data/repository_impl/download_repository_impl.dart';
import 'package:hadi_hoda_flutter/features/download/domain/repository/download_repository.dart';
import 'package:hadi_hoda_flutter/features/download/domain/usecases/get_audios_usecase.dart';
import 'package:hadi_hoda_flutter/features/download/domain/usecases/loading_stream_audio_usecase.dart';
import 'package:hadi_hoda_flutter/features/download/domain/usecases/get_images_usecase.dart';
import 'package:hadi_hoda_flutter/features/download/domain/usecases/loading_stream_usecase.dart';
import 'package:hadi_hoda_flutter/features/download/domain/usecases/save_levels_usecase.dart';
import 'package:hadi_hoda_flutter/features/intro/data/datasource/intro_datasource.dart';
import 'package:hadi_hoda_flutter/features/intro/data/repository_impl/intro_repository_impl.dart';
import 'package:hadi_hoda_flutter/features/intro/domain/repository/intro_repository.dart';
import 'package:hadi_hoda_flutter/features/intro/domain/usecases/get_images_usecase.dart';
import 'package:hadi_hoda_flutter/features/intro/domain/usecases/loading_stream_usecase.dart';
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';
@ -50,17 +46,14 @@ void initBindings() {
locator.registerLazySingleton<GetSampleUseCase>(() => GetSampleUseCase(locator()));
/// Intro Feature
locator.registerLazySingleton<IIntroDatasource>(() => IntroDatasourceImpl(locator()));
locator.registerLazySingleton<IIntroRepository>(() => IntroRepositoryImpl(locator()));
locator.registerLazySingleton<GetImagesUseCase>(() => GetImagesUseCase(locator()));
locator.registerLazySingleton<LoadingStreamUseCase>(() => LoadingStreamUseCase(locator()));
/// Download Feature
locator.registerLazySingleton<IDownloadDatasource>(() => DownloadDatasourceImpl(locator()));
locator.registerLazySingleton<IDownloadRepository>(() => DownloadRepositoryImpl(locator()));
locator.registerLazySingleton<GetImagesUseCase>(() => GetImagesUseCase(locator()));
locator.registerLazySingleton<GetAudiosUseCase>(() => GetAudiosUseCase(locator()));
locator.registerLazySingleton<SaveLevelsUseCase>(() => SaveLevelsUseCase(locator()));
locator.registerLazySingleton<LoadingStreamAudioUseCase>(() => LoadingStreamAudioUseCase(locator()));
locator.registerLazySingleton<LoadingStreamUseCase>(() => LoadingStreamUseCase(locator()));
/// Language Feature

12
pubspec.lock

@ -299,14 +299,6 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
flutter_svg:
dependency: "direct main"
description:
name: flutter_svg
sha256: b9c2ad5872518a27507ab432d1fb97e8813b05f0fc693f9d40fad06d073e0678
url: "https://pub.dev"
source: hosted
version: "2.2.1"
flutter_test:
dependency: "direct dev"
description: flutter
@ -899,7 +891,7 @@ packages:
source: hosted
version: "4.5.1"
vector_graphics:
dependency: transitive
dependency: "direct main"
description:
name: vector_graphics
sha256: a4f059dc26fc8295b5921376600a194c4ec7d55e72f2fe4c7d2831e103d461e6
@ -915,7 +907,7 @@ packages:
source: hosted
version: "1.1.13"
vector_graphics_compiler:
dependency: transitive
dependency: "direct dev"
description:
name: vector_graphics_compiler
sha256: d354a7ec6931e6047785f4db12a1f61ec3d43b207fc0790f863818543f8ff0dc

6
pubspec.yaml

@ -18,7 +18,6 @@ dependencies:
flutter_bloc: ^9.1.1
flutter_localizations:
sdk: flutter
flutter_svg: ^2.2.1
get_it: ^8.2.0
go_router: ^16.1.0
hive: ^2.2.3
@ -29,6 +28,7 @@ dependencies:
pretty_dio_logger: ^1.4.0
shared_preferences: ^2.5.3
showcaseview: ^4.0.1
vector_graphics: ^1.1.19
dev_dependencies:
flutter_test:
@ -36,6 +36,7 @@ dev_dependencies:
flutter_lints: ^5.0.0
hive_generator: ^2.0.1
build_runner: ^2.4.13
vector_graphics_compiler: ^1.1.19
flutter:
uses-material-design: true
@ -44,6 +45,9 @@ flutter:
assets:
- assets/fonts/
- assets/images/
- path: assets/svg/
transformers:
- package: vector_graphics_compiler
fonts:

Loading…
Cancel
Save