From a2ef01dcad92d507de6debe1be0163a78abef8de Mon Sep 17 00:00:00 2001 From: Hugo Pointcheval Date: Thu, 28 Jul 2022 11:05:59 +0200 Subject: [PATCH] feat: update wyatt clean code app with buildable app --- apps/wyatt_clean_code/generate.sh | 4 +- bricks/wyatt_clean_code/__brick__/.gitignore | 47 ++ bricks/wyatt_clean_code/__brick__/.metadata | 30 + .../__brick__/.vscode/launch.json | 116 ++- .../__brick__/.vscode/settings.json | 1 + bricks/wyatt_clean_code/__brick__/Makefile | 24 +- bricks/wyatt_clean_code/__brick__/README.md | 16 + .../__brick__/analysis_options.yaml | 42 +- .../__brick__/assets/colors.xml | 61 ++ .../__brick__/assets/colors/dark.xml | 9 - .../__brick__/assets/fonts/.gitkeep | 1 + .../__brick__/assets/images/.gitkeep | 0 .../assets/images/wyatt-studio-logo.png | Bin 0 -> 11611 bytes .../enable_l10n}} => l10n}/intl_fr.arb | 9 + .../wyatt_clean_code/__brick__/lib/app.dart | 26 - .../__brick__/lib/bootstrap.dart | 46 ++ .../__brick__/lib/core/constants/.gitkeep | 1 + .../lib/core/dependency_injection/get_it.dart | 15 + .../lib/core/design_system/colors.dart | 2 + .../lib/core/design_system/sizing.dart | 235 ++++++ .../lib/core/design_system/theme.dart | 240 ++++++ .../lib/core/design_system/typography.dart | 115 +++ .../__brick__/lib/core/enums/.gitkeep | 0 .../lib/core/enums/exception_type.dart | 7 + .../__brick__/lib/core/enums/flavor.dart | 12 + .../__brick__/lib/core/errors/.gitkeep | 0 .../__brick__/lib/core/errors/exceptions.dart | 29 + .../__brick__/lib/core/extensions/.gitkeep | 0 ...le_l10n}} => build_context_extension.dart} | 2 +- .../lib/core/extensions/num_extension.dart | 9 + .../lib/core/extensions/object_extension.dart | 32 + .../lib/core/flavors/flavor_settings.dart | 64 ++ .../lib/core/mixins/local_data_source.dart | 6 + .../lib/core/mixins/remote_data_source.dart | 6 + .../lib/core/resources/app_theme.dart | 8 - .../enable_router}} | 28 - .../__brick__/lib/core/routes/router.dart | 37 + .../__brick__/lib/core/usecases/usecase.dart | 13 + .../lib/core/utils/app_bloc_observer.dart | 19 +- .../__brick__/lib/core/utils/screen_util.dart | 107 +++ .../lib/core/utils/wyatt_printer.dart | 43 ++ .../lib/data/data_sources/local/.gitkeep | 1 + .../lib/data/data_sources/remote/.gitkeep | 1 + .../__brick__/lib/data/models/.gitkeep | 1 + .../__brick__/lib/data/providers/.gitkeep | 0 .../__brick__/lib/data/repositories/.gitkeep | 0 .../repositories/counter_repository_impl.dart | 24 + .../domain/data_sources/base_data_source.dart | 1 + .../local/base_local_data_source.dart | 3 + .../remote/base_remote_data_source.dart | 3 + .../__brick__/lib/domain/entities/.gitkeep | 1 + .../lib/domain/repositories/.gitkeep | 0 .../domain/repositories/base_repository.dart | 1 + .../repositories/counter_repository.dart | 8 + .../usecases/counter/decrement_counter.dart | 16 + .../usecases/counter/increment_counter.dart | 16 + .../__brick__/lib/gen/assets.gen.dart | 87 +++ .../__brick__/lib/gen/colors.gen.dart | 195 +++++ .../wyatt_clean_code/__brick__/lib/main.dart | 18 - .../__brick__/lib/main_development.dart | 8 + .../__brick__/lib/main_production.dart | 8 + .../__brick__/lib/main_staging.dart | 8 + .../bloc/counter_cubit/counter_cubit.dart | 8 - .../lib/presentation/features/app/app.dart | 71 ++ .../features/counter/blocs/counter_cubit.dart | 39 + .../features/counter/counter_page.dart | 11 + .../counter_page_provider.dart | 31 + .../counter_text_consumer.dart | 11 + .../counter/widgets/counter_base.dart | 54 ++ .../counter/widgets/counter_text.dart | 18 + .../features/initial/initial_page.dart | 32 + .../pages/counter/counter_page.dart | 40 - .../pages/counter/widgets/counter_text.dart | 14 - .../pages/initial/initial_page.dart | 26 - .../lib/presentation/shared/layouts/.gitkeep | 0 .../shared/layouts/app_default_scaffold.dart | 27 + .../shared/state_management/.gitkeep | 1 + .../counter_state_management.dart | 26 - .../lib/presentation/shared/widgets/.gitkeep | 0 .../__brick__/lib/widget_tree.dart | 63 -- .../wyatt_clean_code/__brick__/pubspec.yaml | 134 ++-- .../__brick__/scripts/.gitkeep | 0 .../enable_android}}/app/build.gradle | 52 +- .../app/src/debug/AndroidManifest.xml | 2 +- .../app/src/main/AndroidManifest.xml | 4 +- .../pathCase}}/MainActivity.kt | 2 +- .../app/src/profile/AndroidManifest.xml | 2 +- .../Runner.xcodeproj/project.pbxproj | 696 +++++++++++++++++- .../xcschemes/development.xcscheme | 78 ++ .../xcschemes/production.xcscheme | 78 ++ .../xcshareddata/xcschemes/staging.xcscheme | 78 ++ .../enable_ios}}/Runner/Info.plist | 8 +- .../enable_web}}/index.html | 4 +- .../enable_web}}/manifest.json | 4 +- bricks/wyatt_clean_code/brick.yaml | 17 +- bricks/wyatt_clean_code/hooks/post_gen.dart | 1 + 96 files changed, 3118 insertions(+), 376 deletions(-) create mode 100644 bricks/wyatt_clean_code/__brick__/.gitignore create mode 100644 bricks/wyatt_clean_code/__brick__/.metadata create mode 100644 bricks/wyatt_clean_code/__brick__/README.md create mode 100644 bricks/wyatt_clean_code/__brick__/assets/colors.xml delete mode 100644 bricks/wyatt_clean_code/__brick__/assets/colors/dark.xml delete mode 100644 bricks/wyatt_clean_code/__brick__/assets/images/.gitkeep create mode 100644 bricks/wyatt_clean_code/__brick__/assets/images/wyatt-studio-logo.png rename bricks/wyatt_clean_code/__brick__/assets/{{{#enable_l10n}}l10n{{/enable_l10n}} => l10n}/intl_fr.arb (54%) delete mode 100644 bricks/wyatt_clean_code/__brick__/lib/app.dart create mode 100644 bricks/wyatt_clean_code/__brick__/lib/bootstrap.dart create mode 100644 bricks/wyatt_clean_code/__brick__/lib/core/constants/.gitkeep create mode 100644 bricks/wyatt_clean_code/__brick__/lib/core/dependency_injection/get_it.dart create mode 100644 bricks/wyatt_clean_code/__brick__/lib/core/design_system/colors.dart create mode 100644 bricks/wyatt_clean_code/__brick__/lib/core/design_system/sizing.dart create mode 100644 bricks/wyatt_clean_code/__brick__/lib/core/design_system/theme.dart create mode 100644 bricks/wyatt_clean_code/__brick__/lib/core/design_system/typography.dart delete mode 100644 bricks/wyatt_clean_code/__brick__/lib/core/enums/.gitkeep create mode 100644 bricks/wyatt_clean_code/__brick__/lib/core/enums/exception_type.dart create mode 100644 bricks/wyatt_clean_code/__brick__/lib/core/enums/flavor.dart delete mode 100644 bricks/wyatt_clean_code/__brick__/lib/core/errors/.gitkeep create mode 100644 bricks/wyatt_clean_code/__brick__/lib/core/errors/exceptions.dart delete mode 100644 bricks/wyatt_clean_code/__brick__/lib/core/extensions/.gitkeep rename bricks/wyatt_clean_code/__brick__/lib/core/extensions/{{{#enable_l10n}}app_localizations_x.dart{{/enable_l10n}} => build_context_extension.dart} (83%) create mode 100644 bricks/wyatt_clean_code/__brick__/lib/core/extensions/num_extension.dart create mode 100644 bricks/wyatt_clean_code/__brick__/lib/core/extensions/object_extension.dart create mode 100644 bricks/wyatt_clean_code/__brick__/lib/core/flavors/flavor_settings.dart create mode 100644 bricks/wyatt_clean_code/__brick__/lib/core/mixins/local_data_source.dart create mode 100644 bricks/wyatt_clean_code/__brick__/lib/core/mixins/remote_data_source.dart delete mode 100644 bricks/wyatt_clean_code/__brick__/lib/core/resources/app_theme.dart delete mode 100644 bricks/wyatt_clean_code/__brick__/lib/core/resources/{{#enable_router}}app_router.dart{{/enable_router}} create mode 100644 bricks/wyatt_clean_code/__brick__/lib/core/routes/router.dart create mode 100644 bricks/wyatt_clean_code/__brick__/lib/core/usecases/usecase.dart create mode 100644 bricks/wyatt_clean_code/__brick__/lib/core/utils/screen_util.dart create mode 100644 bricks/wyatt_clean_code/__brick__/lib/core/utils/wyatt_printer.dart create mode 100644 bricks/wyatt_clean_code/__brick__/lib/data/data_sources/local/.gitkeep create mode 100644 bricks/wyatt_clean_code/__brick__/lib/data/data_sources/remote/.gitkeep delete mode 100644 bricks/wyatt_clean_code/__brick__/lib/data/providers/.gitkeep delete mode 100644 bricks/wyatt_clean_code/__brick__/lib/data/repositories/.gitkeep create mode 100644 bricks/wyatt_clean_code/__brick__/lib/data/repositories/counter_repository_impl.dart create mode 100644 bricks/wyatt_clean_code/__brick__/lib/domain/data_sources/base_data_source.dart create mode 100644 bricks/wyatt_clean_code/__brick__/lib/domain/data_sources/local/base_local_data_source.dart create mode 100644 bricks/wyatt_clean_code/__brick__/lib/domain/data_sources/remote/base_remote_data_source.dart delete mode 100644 bricks/wyatt_clean_code/__brick__/lib/domain/repositories/.gitkeep create mode 100644 bricks/wyatt_clean_code/__brick__/lib/domain/repositories/base_repository.dart create mode 100644 bricks/wyatt_clean_code/__brick__/lib/domain/repositories/counter_repository.dart create mode 100644 bricks/wyatt_clean_code/__brick__/lib/domain/usecases/counter/decrement_counter.dart create mode 100644 bricks/wyatt_clean_code/__brick__/lib/domain/usecases/counter/increment_counter.dart create mode 100644 bricks/wyatt_clean_code/__brick__/lib/gen/assets.gen.dart create mode 100644 bricks/wyatt_clean_code/__brick__/lib/gen/colors.gen.dart delete mode 100644 bricks/wyatt_clean_code/__brick__/lib/main.dart create mode 100644 bricks/wyatt_clean_code/__brick__/lib/main_development.dart create mode 100644 bricks/wyatt_clean_code/__brick__/lib/main_production.dart create mode 100644 bricks/wyatt_clean_code/__brick__/lib/main_staging.dart delete mode 100644 bricks/wyatt_clean_code/__brick__/lib/presentation/bloc/counter_cubit/counter_cubit.dart create mode 100644 bricks/wyatt_clean_code/__brick__/lib/presentation/features/app/app.dart create mode 100644 bricks/wyatt_clean_code/__brick__/lib/presentation/features/counter/blocs/counter_cubit.dart create mode 100644 bricks/wyatt_clean_code/__brick__/lib/presentation/features/counter/counter_page.dart create mode 100644 bricks/wyatt_clean_code/__brick__/lib/presentation/features/counter/state_management/counter_page_provider.dart create mode 100644 bricks/wyatt_clean_code/__brick__/lib/presentation/features/counter/state_management/counter_text_consumer.dart create mode 100644 bricks/wyatt_clean_code/__brick__/lib/presentation/features/counter/widgets/counter_base.dart create mode 100644 bricks/wyatt_clean_code/__brick__/lib/presentation/features/counter/widgets/counter_text.dart create mode 100644 bricks/wyatt_clean_code/__brick__/lib/presentation/features/initial/initial_page.dart delete mode 100644 bricks/wyatt_clean_code/__brick__/lib/presentation/pages/counter/counter_page.dart delete mode 100644 bricks/wyatt_clean_code/__brick__/lib/presentation/pages/counter/widgets/counter_text.dart delete mode 100644 bricks/wyatt_clean_code/__brick__/lib/presentation/pages/initial/initial_page.dart delete mode 100644 bricks/wyatt_clean_code/__brick__/lib/presentation/shared/layouts/.gitkeep create mode 100644 bricks/wyatt_clean_code/__brick__/lib/presentation/shared/layouts/app_default_scaffold.dart create mode 100644 bricks/wyatt_clean_code/__brick__/lib/presentation/shared/state_management/.gitkeep delete mode 100644 bricks/wyatt_clean_code/__brick__/lib/presentation/shared/state_management/counter_state_management.dart delete mode 100644 bricks/wyatt_clean_code/__brick__/lib/presentation/shared/widgets/.gitkeep delete mode 100644 bricks/wyatt_clean_code/__brick__/lib/widget_tree.dart delete mode 100644 bricks/wyatt_clean_code/__brick__/scripts/.gitkeep create mode 100644 bricks/wyatt_clean_code/__brick__/{{#enable_ios}}ios{{/enable_ios}}/Runner.xcodeproj/xcshareddata/xcschemes/development.xcscheme create mode 100644 bricks/wyatt_clean_code/__brick__/{{#enable_ios}}ios{{/enable_ios}}/Runner.xcodeproj/xcshareddata/xcschemes/production.xcscheme create mode 100644 bricks/wyatt_clean_code/__brick__/{{#enable_ios}}ios{{/enable_ios}}/Runner.xcodeproj/xcshareddata/xcschemes/staging.xcscheme diff --git a/apps/wyatt_clean_code/generate.sh b/apps/wyatt_clean_code/generate.sh index 58ddeb1..ac3f503 100755 --- a/apps/wyatt_clean_code/generate.sh +++ b/apps/wyatt_clean_code/generate.sh @@ -3,6 +3,7 @@ make clean rm -rf .idea rm -f wyatt_clean_code.iml +rm .fvm/flutter_sdk cd ../../ echo "Brick generator..." dart tools/brick_generator/bin/brick_generator.dart wyatt_clean_code wyatt_clean_code wyatt-clean-code "Wyatt Demo" com.example.wyatt_clean_code @@ -17,4 +18,5 @@ mv -f bricks/wyatt_clean_code/__brick__/ios/ bricks/wyatt_clean_code/__brick__/{ mkdir bricks/wyatt_clean_code/__brick__/{{#enable_web}}web\{\{ mv -f bricks/wyatt_clean_code/__brick__/web/ bricks/wyatt_clean_code/__brick__/{{#enable_web}}web{{/enable_web}} -rm bricks/wyatt_clean_code/__brick__/generate.sh \ No newline at end of file +rm bricks/wyatt_clean_code/__brick__/generate.sh +rm -rf bricks/wyatt_clean_code/__brick__/.fvm/flutter_sdk \ No newline at end of file diff --git a/bricks/wyatt_clean_code/__brick__/.gitignore b/bricks/wyatt_clean_code/__brick__/.gitignore new file mode 100644 index 0000000..a8e938c --- /dev/null +++ b/bricks/wyatt_clean_code/__brick__/.gitignore @@ -0,0 +1,47 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ +migrate_working_dir/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +**/doc/api/ +**/ios/Flutter/.last_build_id +.dart_tool/ +.flutter-plugins +.flutter-plugins-dependencies +.packages +.pub-cache/ +.pub/ +/build/ + +# Web related +lib/generated_plugin_registrant.dart + +# Symbolication related +app.*.symbols + +# Obfuscation related +app.*.map.json + +# Android Studio will place build artifacts here +/android/app/debug +/android/app/profile +/android/app/release diff --git a/bricks/wyatt_clean_code/__brick__/.metadata b/bricks/wyatt_clean_code/__brick__/.metadata new file mode 100644 index 0000000..2112298 --- /dev/null +++ b/bricks/wyatt_clean_code/__brick__/.metadata @@ -0,0 +1,30 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled. + +version: + revision: f1875d570e39de09040c8f79aa13cc56baab8db1 + channel: stable + +project_type: app + +# Tracks metadata for the flutter migrate command +migration: + platforms: + - platform: root + create_revision: f1875d570e39de09040c8f79aa13cc56baab8db1 + base_revision: f1875d570e39de09040c8f79aa13cc56baab8db1 + - platform: web + create_revision: f1875d570e39de09040c8f79aa13cc56baab8db1 + base_revision: f1875d570e39de09040c8f79aa13cc56baab8db1 + + # User provided section + + # List of Local paths (relative to this file) that should be + # ignored by the migrate tool. + # + # Files that are not part of the templates will be ignored by default. + unmanaged_files: + - 'lib/main.dart' + - 'ios/Runner.xcodeproj/project.pbxproj' diff --git a/bricks/wyatt_clean_code/__brick__/.vscode/launch.json b/bricks/wyatt_clean_code/__brick__/.vscode/launch.json index 96763cd..40a2104 100644 --- a/bricks/wyatt_clean_code/__brick__/.vscode/launch.json +++ b/bricks/wyatt_clean_code/__brick__/.vscode/launch.json @@ -5,21 +5,121 @@ "version": "0.2.0", "configurations": [ { - "name": "{{#snakeCase}}{{project_name}}{{/snakeCase}}", - "request": "launch", - "type": "dart" - }, - { - "name": "{{#snakeCase}}{{project_name}}{{/snakeCase}} (profile mode)", + "name": "Launch development", "request": "launch", "type": "dart", + "program": "lib/main_development.dart", + "args": [ + "--flavor", + "development", + "--target", + "lib/main_development.dart" + ], + "flutterMode": "debug" + }, + { + "name": "Launch development in profile mode", + "request": "launch", + "type": "dart", + "program": "lib/main_development.dart", + "args": [ + "--flavor", + "development", + "--target", + "lib/main_development.dart" + ], "flutterMode": "profile" }, { - "name": "{{#snakeCase}}{{project_name}}{{/snakeCase}} (release mode)", + "name": "Launch development in release mode", "request": "launch", "type": "dart", + "program": "lib/main_development.dart", + "args": [ + "--flavor", + "development", + "--target", + "lib/main_development.dart" + ], "flutterMode": "release" - } + }, + { + "name": "Launch staging", + "request": "launch", + "type": "dart", + "program": "lib/main_staging.dart", + "args": [ + "--flavor", + "staging", + "--target", + "lib/main_staging.dart" + ], + "flutterMode": "debug" + }, + { + "name": "Launch staging in profile mode", + "request": "launch", + "type": "dart", + "program": "lib/main_staging.dart", + "args": [ + "--flavor", + "staging", + "--target", + "lib/main_staging.dart" + ], + "flutterMode": "profile" + }, + { + "name": "Launch staging in release mode", + "request": "launch", + "type": "dart", + "program": "lib/main_staging.dart", + "args": [ + "--flavor", + "staging", + "--target", + "lib/main_staging.dart" + ], + "flutterMode": "release" + }, + { + "name": "Launch production", + "request": "launch", + "type": "dart", + "program": "lib/main_production.dart", + "args": [ + "--flavor", + "production", + "--target", + "lib/main_production.dart" + ], + "flutterMode": "debug" + }, + { + "name": "Launch production in profile mode", + "request": "launch", + "type": "dart", + "program": "lib/main_production.dart", + "args": [ + "--flavor", + "production", + "--target", + "lib/main_production.dart" + ], + "flutterMode": "profile" + }, + { + "name": "Launch production in release mode", + "request": "launch", + "type": "dart", + "program": "lib/main_production.dart", + "args": [ + "--flavor", + "production", + "--target", + "lib/main_production.dart" + ], + "flutterMode": "release" + }, ] } \ No newline at end of file diff --git a/bricks/wyatt_clean_code/__brick__/.vscode/settings.json b/bricks/wyatt_clean_code/__brick__/.vscode/settings.json index 855293b..fa6f612 100644 --- a/bricks/wyatt_clean_code/__brick__/.vscode/settings.json +++ b/bricks/wyatt_clean_code/__brick__/.vscode/settings.json @@ -1,4 +1,5 @@ { + "dart.flutterSdkPath": ".fvm/flutter_sdk", "bloc.newCubitTemplate.type": "equatable", "psi-header.config": { "blankLinesAfter": 0, diff --git a/bricks/wyatt_clean_code/__brick__/Makefile b/bricks/wyatt_clean_code/__brick__/Makefile index f46b81c..a9a3ef9 100644 --- a/bricks/wyatt_clean_code/__brick__/Makefile +++ b/bricks/wyatt_clean_code/__brick__/Makefile @@ -1,4 +1,4 @@ -.PHONY: help clean get upgrade format lint gen +.PHONY: help clean get upgrade format lint gen watch run-dev run-stg run-prod # Adding a help file: https://gist.github.com/prwhite/8168133#gistcomment-1313022 help: ## This help dialog. @@ -33,6 +33,22 @@ lint: ## Lints the code. @echo "• Verifying code..." @dart analyze . || (echo "Error in project"; exit 1) -gen: get ## Run build_runner (Freezed, Fluttergen, etc...) - @echo "• Running build_runner scripts" - @flutter pub run build_runner build \ No newline at end of file +gen: get ## Run build_runner build (Freezed, Fluttergen, Hive etc...) + @echo "• build_runner build" + @flutter pub run build_runner build + +watch: get ## Run build_runner watch (Freezed, Fluttergen, Hive etc...) + @echo "• build_runner watch" + @flutter pub run build_runner watch + +run-dev: ## Run app in development mode + @echo "• Running the app (development)" + @flutter run --flavor development --target lib/main_development.dart + +run-stg: ## Run app in staging mode + @echo "• Running the app (staging)" + @flutter run --flavor staging --target lib/main_staging.dart + +run-prod: ## Run app in production mode + @echo "• Running the app (production)" + @flutter run --flavor production --target lib/main_production.dart \ No newline at end of file diff --git a/bricks/wyatt_clean_code/__brick__/README.md b/bricks/wyatt_clean_code/__brick__/README.md new file mode 100644 index 0000000..4136204 --- /dev/null +++ b/bricks/wyatt_clean_code/__brick__/README.md @@ -0,0 +1,16 @@ +# {{#snakeCase}}{{project_name}}{{/snakeCase}} + +{{{description}}} + +## Getting Started + +This project is a starting point for a Flutter application. + +A few resources to get you started if this is your first Flutter project: + +- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab) +- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook) + +For help getting started with Flutter development, view the +[online documentation](https://docs.flutter.dev/), which offers tutorials, +samples, guidance on mobile development, and a full API reference. diff --git a/bricks/wyatt_clean_code/__brick__/analysis_options.yaml b/bricks/wyatt_clean_code/__brick__/analysis_options.yaml index d00274d..9bdb566 100644 --- a/bricks/wyatt_clean_code/__brick__/analysis_options.yaml +++ b/bricks/wyatt_clean_code/__brick__/analysis_options.yaml @@ -1,9 +1,35 @@ -# {{#enable_analysis}} -include: package:wyatt_analysis/analysis_options.flutter.experimental.yaml +# This file configures the analyzer, which statically analyzes Dart code to +# check for errors, warnings, and lints. +# +# The issues identified by the analyzer are surfaced in the UI of Dart-enabled +# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be +# invoked from the command line by running `flutter analyze`. -analyzer: - strong-mode: - implicit-dynamic: true -# {{/enable_analysis}}{{^enable_analysis}} -include: package:flutter_lints/flutter.yaml -# {{/enable_analysis}} \ No newline at end of file +# The following line activates a set of recommended lints for Flutter by +# Wyatt Studio, for apps packages, and plugins designed to +# encourage good coding practices. +include: package:wyatt_analysis/analysis_options.flutter.yaml + +analyzer: + exclude: + - '**/*.g.dart' + - '**/*.freezed.dart' + +linter: + # The lint rules applied to this project can be customized in the + # section below to disable rules from the `package:flutter_lints/flutter.yaml` + # included above or to enable additional rules. A list of all available lints + # and their documentation is published at + # https://dart-lang.github.io/linter/lints/index.html. + # + # Instead of disabling a lint rule for the entire project in the + # section below, it can also be suppressed for a single line of code + # or a specific dart file by using the `// ignore: name_of_lint` and + # `// ignore_for_file: name_of_lint` syntax on the line or in the file + # producing the lint. + rules: + # avoid_print: false # Uncomment to disable the `avoid_print` rule + # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/bricks/wyatt_clean_code/__brick__/assets/colors.xml b/bricks/wyatt_clean_code/__brick__/assets/colors.xml new file mode 100644 index 0000000..f5e9c9a --- /dev/null +++ b/bricks/wyatt_clean_code/__brick__/assets/colors.xml @@ -0,0 +1,61 @@ + + + #FF2196F3 + + #FF0061A6 + #FFFFFFFF + #FFD0E4FF + #FF001D36 + + #FF535F70 + #FFFFFFFF + #FFD6E3F7 + #FF101C2B + + #FFBA1B1B + #FFFFFFFF + #FFFFDAD4 + #FF410001 + + #FFFDFCFF + #FF1B1B1B + #FFFDFCFF + #FF1B1B1B + #FFDFE2EB + #FF42474E + #FF73777F + #FF000000 + + #FF2F3033 + #FFF1F0F4 + #FF9CCAFF + + + #FF9CCAFF + #FF00325A + #FF00497F + #FFD0E4FF + + #FFBBC8DB + #FF253140 + #FF3C4858 + #FFD6E3F7 + + #FFFFB4A9 + #FF680003 + #FF930006 + #FFFFB4A9 + + #FF1B1B1B + #FFE2E2E6 + #FF1B1B1B + #FFE2E2E6 + #FF42474E + #FFC3C7D0 + #FF8D9199 + #FF000000 + + #FFE2E2E6 + #FF2F3033 + #FF0061A6 + \ No newline at end of file diff --git a/bricks/wyatt_clean_code/__brick__/assets/colors/dark.xml b/bricks/wyatt_clean_code/__brick__/assets/colors/dark.xml deleted file mode 100644 index 76afbe8..0000000 --- a/bricks/wyatt_clean_code/__brick__/assets/colors/dark.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - #FFFFFF - #000000 - #EEEEEE - #979797 - #CF2A2A - #DF9527 - \ No newline at end of file diff --git a/bricks/wyatt_clean_code/__brick__/assets/fonts/.gitkeep b/bricks/wyatt_clean_code/__brick__/assets/fonts/.gitkeep index e69de29..f94cb6f 100644 --- a/bricks/wyatt_clean_code/__brick__/assets/fonts/.gitkeep +++ b/bricks/wyatt_clean_code/__brick__/assets/fonts/.gitkeep @@ -0,0 +1 @@ +# just to keep empty folder in brick generation \ No newline at end of file diff --git a/bricks/wyatt_clean_code/__brick__/assets/images/.gitkeep b/bricks/wyatt_clean_code/__brick__/assets/images/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/bricks/wyatt_clean_code/__brick__/assets/images/wyatt-studio-logo.png b/bricks/wyatt_clean_code/__brick__/assets/images/wyatt-studio-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..322633e83a745133b19a6feb60ac34ddcdd83f33 GIT binary patch literal 11611 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 CYmw>z literal 0 HcmV?d00001 diff --git a/bricks/wyatt_clean_code/__brick__/assets/{{#enable_l10n}}l10n{{/enable_l10n}}/intl_fr.arb b/bricks/wyatt_clean_code/__brick__/assets/l10n/intl_fr.arb similarity index 54% rename from bricks/wyatt_clean_code/__brick__/assets/{{#enable_l10n}}l10n{{/enable_l10n}}/intl_fr.arb rename to bricks/wyatt_clean_code/__brick__/assets/l10n/intl_fr.arb index 1a6db0f..b95f76d 100644 --- a/bricks/wyatt_clean_code/__brick__/assets/{{#enable_l10n}}l10n{{/enable_l10n}}/intl_fr.arb +++ b/bricks/wyatt_clean_code/__brick__/assets/l10n/intl_fr.arb @@ -4,6 +4,15 @@ "@counterAppBarTitle": { "description": "Texte affiché dans l'AppBar de la page Compteur" }, + "youHavePushed": "Vous avez appuyé {count} fois sur le bouton !", + "@youHavePushed": { + "description": "Message affiché sur la page compteur", + "placeholders": { + "count": { + "type": "int" + } + } + }, "goToCounter": "Aller au Compteur", "@goToCounter": { "description": "Texte affiché dans le bouton ammenant vers la page Compteur" diff --git a/bricks/wyatt_clean_code/__brick__/lib/app.dart b/bricks/wyatt_clean_code/__brick__/lib/app.dart deleted file mode 100644 index cb21a0e..0000000 --- a/bricks/wyatt_clean_code/__brick__/lib/app.dart +++ /dev/null @@ -1,26 +0,0 @@ -import 'package:{{project_name.snakeCase()}}/widget_tree.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -{{#enable_auth}}import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart';{{/enable_auth}} - -class App extends StatelessWidget { - const App({super.key}); - - @override - Widget build(BuildContext context) { - // Data providers - // ... - // return MultiRepositoryProvider( - // providers: [ - // // Repositories - // ], - // child: MultiBlocProvider( - // providers: [ - // // Toplevel Blocs and Cubits - // ], - // child: const WidgetTree(), - // ), - // ); - return const WidgetTree(); - } -} diff --git a/bricks/wyatt_clean_code/__brick__/lib/bootstrap.dart b/bricks/wyatt_clean_code/__brick__/lib/bootstrap.dart new file mode 100644 index 0000000..55dec5e --- /dev/null +++ b/bricks/wyatt_clean_code/__brick__/lib/bootstrap.dart @@ -0,0 +1,46 @@ +import 'dart:async'; + +import 'package:flutter/foundation.dart'; +import 'package:flutter/widgets.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:go_router/go_router.dart'; +import 'package:{{#snakeCase}}{{project_name}}{{/snakeCase}}/core/dependency_injection/get_it.dart'; +import 'package:{{#snakeCase}}{{project_name}}{{/snakeCase}}/core/flavors/flavor_settings.dart'; +import 'package:{{#snakeCase}}{{project_name}}{{/snakeCase}}/core/utils/app_bloc_observer.dart'; +import 'package:{{#snakeCase}}{{project_name}}{{/snakeCase}}/core/utils/wyatt_printer.dart'; + +Future bootstrap(FutureOr Function() builder) async { + await runZonedGuarded( + () async { + WidgetsFlutterBinding.ensureInitialized(); + + FlutterError.onError = (details) { + WyattPrinter.get().e( + '', + details, + details.stack, + ); + }; + + FlavorSettings.init(); + GetItInitializer.run(); + + GoRouter.setUrlPathStrategy(UrlPathStrategy.path); + + if (!kReleaseMode) { + final env = FlavorSettings.get(); + WyattPrinter.get().i('Flavor : ${env.flavor.name}'); + } + + await BlocOverrides.runZoned( + () async => runApp(await builder()), + blocObserver: AppBlocObserver(), + ); + }, + (error, stackTrace) => WyattPrinter.get().e( + '', + error, + stackTrace, + ), + ); +} diff --git a/bricks/wyatt_clean_code/__brick__/lib/core/constants/.gitkeep b/bricks/wyatt_clean_code/__brick__/lib/core/constants/.gitkeep new file mode 100644 index 0000000..f94cb6f --- /dev/null +++ b/bricks/wyatt_clean_code/__brick__/lib/core/constants/.gitkeep @@ -0,0 +1 @@ +# just to keep empty folder in brick generation \ No newline at end of file diff --git a/bricks/wyatt_clean_code/__brick__/lib/core/dependency_injection/get_it.dart b/bricks/wyatt_clean_code/__brick__/lib/core/dependency_injection/get_it.dart new file mode 100644 index 0000000..7180ebb --- /dev/null +++ b/bricks/wyatt_clean_code/__brick__/lib/core/dependency_injection/get_it.dart @@ -0,0 +1,15 @@ +import 'dart:async'; + +import 'package:get_it/get_it.dart'; + +final getIt = GetIt.I; + +abstract class GetItInitializer { + static Future init() async { + // Here, register data sources + } + + static void run() { + unawaited(init()); + } +} diff --git a/bricks/wyatt_clean_code/__brick__/lib/core/design_system/colors.dart b/bricks/wyatt_clean_code/__brick__/lib/core/design_system/colors.dart new file mode 100644 index 0000000..a4ea53c --- /dev/null +++ b/bricks/wyatt_clean_code/__brick__/lib/core/design_system/colors.dart @@ -0,0 +1,2 @@ +/// Generate colors with `flutter pub run build_runner build` +export 'package:{{#snakeCase}}{{project_name}}{{/snakeCase}}/gen/colors.gen.dart'; diff --git a/bricks/wyatt_clean_code/__brick__/lib/core/design_system/sizing.dart b/bricks/wyatt_clean_code/__brick__/lib/core/design_system/sizing.dart new file mode 100644 index 0000000..1c4fdc0 --- /dev/null +++ b/bricks/wyatt_clean_code/__brick__/lib/core/design_system/sizing.dart @@ -0,0 +1,235 @@ +import 'package:flutter/material.dart'; +import 'package:gap/gap.dart'; + +/// Geometric progression. +abstract class AppSizing { + /// Default to 1 + static const double factor = 1; + + /// SizedBox.shrink(); + static const SizedBox empty = SizedBox.shrink(); + + /// xxs = factor * 2 + static const double xxs = factor * 2; + + /// xs = factor * 4 + static const double xs = factor * 4; + + /// s = factor * 8 + static const double s = factor * 8; + + /// m = factor * 16 + static const double m = factor * 16; + + /// l = factor * 32 + static const double l = factor * 32; + + /// xl = factor * 64 + static const double xl = factor * 64; + + /// xxl = factor * 128 + static const double xxl = factor * 128; + + /// xxs = factor * 2 + static const Gap xxsGap = Gap(xxs); + + /// xs = factor * 4 + static const Gap xsGap = Gap(xs); + + /// s = factor * 8 + static const Gap sGap = Gap(s); + + /// m = factor * 16 + static const Gap mGap = Gap(m); + + /// l = factor * 32 + static const Gap lGap = Gap(l); + + /// xl = factor * 64 + static const Gap xlGap = Gap(xl); + + /// xxl = factor * 128 + static const Gap xxlGap = Gap(xxl); + + /// xxs = factor * 2 + static const Radius xxsRadius = Radius.circular(xxs); + + /// xs = factor * 4 + static const Radius xsRadius = Radius.circular(xs); + + /// s = factor * 8 + static const Radius sRadius = Radius.circular(s); + + /// m = factor * 16 + static const Radius mRadius = Radius.circular(m); + + /// l = factor * 32 + static const Radius lRadius = Radius.circular(l); + + /// xl = factor * 64 + static const Radius xlRadius = Radius.circular(xl); + + /// xxl = factor * 128 + static const Radius xxlRadius = Radius.circular(xxl); + + /// xxs = factor * 2 + /// + /// A square inset offers indents content on all four sides. + /// + /// *e.g [EdgeInsets.all(value)]* + static const EdgeInsets xxsSquareInset = EdgeInsets.all(xxs); + + /// xs = factor * 4 + /// + /// A square inset offers indents content on all four sides. + /// + /// *e.g [EdgeInsets.all(value)]* + static const EdgeInsets xsSquareInset = EdgeInsets.all(xs); + + /// s = factor * 8 + /// + /// A square inset offers indents content on all four sides. + /// + /// *e.g [EdgeInsets.all(value)]* + static const EdgeInsets sSquareInset = EdgeInsets.all(s); + + /// m = factor * 16 + /// + /// A square inset offers indents content on all four sides. + /// + /// *e.g [EdgeInsets.all(value)]* + static const EdgeInsets mSquareInset = EdgeInsets.all(m); + + /// l = factor * 32 + /// + /// A square inset offers indents content on all four sides. + /// + /// *e.g [EdgeInsets.all(value)]* + static const EdgeInsets lSquareInset = EdgeInsets.all(l); + + /// xl = factor * 64 + /// + /// A square inset offers indents content on all four sides. + /// + /// *e.g [EdgeInsets.all(value)]* + static const EdgeInsets xlSquareInset = EdgeInsets.all(xl); + + /// xxl = factor * 128 + /// + /// A square inset offers indents content on all four sides. + /// + /// *e.g [EdgeInsets.all(value)]* + static const EdgeInsets xxlSquareInset = EdgeInsets.all(xxl); + + /// xxs = factor * 2 + /// + /// A squished inset reduces space top and bottom by 50%. + /// + /// *e.g [EdgeInsets.symmetric(horizontal: value, vertical: value / 2)]* + static const EdgeInsets xxsSquishInset = + EdgeInsets.symmetric(horizontal: xxs, vertical: xxs / 2); + + /// xs = factor * 4 + /// + /// A squished inset reduces space top and bottom by 50%. + /// + /// *e.g [EdgeInsets.symmetric(horizontal: value, vertical: value / 2)]* + static const EdgeInsets xsSquishInset = + EdgeInsets.symmetric(horizontal: xs, vertical: xs / 2); + + /// s = factor * 8 + /// + /// A squished inset reduces space top and bottom by 50%. + /// + /// *e.g [EdgeInsets.symmetric(horizontal: value, vertical: value / 2)]* + static const EdgeInsets sSquishInset = + EdgeInsets.symmetric(horizontal: s, vertical: s / 2); + + /// m = factor * 16 + /// + /// A squished inset reduces space top and bottom by 50%. + /// + /// *e.g [EdgeInsets.symmetric(horizontal: value, vertical: value / 2)]* + static const EdgeInsets mSquishInset = + EdgeInsets.symmetric(horizontal: m, vertical: m / 2); + + /// l = factor * 32 + /// + /// A squished inset reduces space top and bottom by 50%. + /// + /// *e.g [EdgeInsets.symmetric(horizontal: value, vertical: value / 2)]* + static const EdgeInsets lSquishInset = + EdgeInsets.symmetric(horizontal: l, vertical: l / 2); + + /// xl = factor * 64 + /// + /// A squished inset reduces space top and bottom by 50%. + /// + /// *e.g [EdgeInsets.symmetric(horizontal: value, vertical: value / 2)]* + static const EdgeInsets xlSquishInset = + EdgeInsets.symmetric(horizontal: xl, vertical: xl / 2); + + /// xxl = factor * 128 + /// + /// A squished inset reduces space top and bottom by 50%. + /// + /// *e.g [EdgeInsets.symmetric(horizontal: value, vertical: value / 2)]* + static const EdgeInsets xxlSquishInset = + EdgeInsets.symmetric(horizontal: xxl, vertical: xxl / 2); + + /// xxs = factor * 2 + /// + /// A stretched inset reduces space left and right by 50%. + /// + /// *e.g [EdgeInsets.symmetric(vertical: value, horizontal: value / 2)]* + static const EdgeInsets xxsStretchInset = + EdgeInsets.symmetric(vertical: xxs, horizontal: xxs / 2); + + /// xs = factor * 4 + /// + /// A stretched inset reduces space left and right by 50%. + /// + /// *e.g [EdgeInsets.symmetric(vertical: value, horizontal: value / 2)]* + static const EdgeInsets xsStretchInset = + EdgeInsets.symmetric(vertical: xs, horizontal: xs / 2); + + /// s = factor * 8 + /// + /// A stretched inset reduces space left and right by 50%. + /// + /// *e.g [EdgeInsets.symmetric(vertical: value, horizontal: value / 2)]* + static const EdgeInsets sStretchInset = + EdgeInsets.symmetric(vertical: s, horizontal: s / 2); + + /// m = factor * 16 + /// + /// A stretched inset reduces space left and right by 50%. + /// + /// *e.g [EdgeInsets.symmetric(vertical: value, horizontal: value / 2)]* + static const EdgeInsets mStretchInset = + EdgeInsets.symmetric(vertical: m, horizontal: m / 2); + + /// l = factor * 32 + /// + /// A stretched inset reduces space left and right by 50%. + /// + /// *e.g [EdgeInsets.symmetric(vertical: value, horizontal: value / 2)]* + static const EdgeInsets lStretchInset = + EdgeInsets.symmetric(vertical: l, horizontal: l / 2); + + /// xl = factor * 64 + /// + /// A stretched inset reduces space left and right by 50%. + /// + /// *e.g [EdgeInsets.symmetric(vertical: value, horizontal: value / 2)]* + static const EdgeInsets xlStretchInset = + EdgeInsets.symmetric(vertical: xl, horizontal: xl / 2); + + /// xxl = factor * 128 + /// + /// A stretched inset reduces space left and right by 50%. + /// + /// *e.g [EdgeInsets.symmetric(vertical: value, horizontal: value / 2)]* + static const EdgeInsets xxlStretchInset = + EdgeInsets.symmetric(vertical: xxl, horizontal: xxl / 2); +} diff --git a/bricks/wyatt_clean_code/__brick__/lib/core/design_system/theme.dart b/bricks/wyatt_clean_code/__brick__/lib/core/design_system/theme.dart new file mode 100644 index 0000000..4903272 --- /dev/null +++ b/bricks/wyatt_clean_code/__brick__/lib/core/design_system/theme.dart @@ -0,0 +1,240 @@ +import 'package:flutter/material.dart'; +import 'package:{{#snakeCase}}{{project_name}}{{/snakeCase}}/core/design_system/colors.dart'; +import 'package:{{#snakeCase}}{{project_name}}{{/snakeCase}}/core/design_system/typography.dart'; + +const _smallTextScaleFactor = 0.80; +const _largeTextScaleFactor = 1.20; + +/// Namespace for the [ThemeData]. +class AppTheme { + /// Light `ThemeData` for UI. + static ThemeData get light => ThemeData( + colorScheme: ColorScheme.fromSwatch( + primarySwatch: ColorName.seedColor, + accentColor: ColorName.seedColorAccent, + cardColor: ColorName.lightBackground, + backgroundColor: ColorName.lightBackground, + errorColor: ColorName.lightError, + ), + appBarTheme: _appBarLightTheme, + elevatedButtonTheme: _elevatedButtonLightTheme, + outlinedButtonTheme: _outlinedButtonLightTheme, + textTheme: _textTheme(), + dialogTheme: _dialogLightTheme, + tooltipTheme: _tooltipLightTheme, + bottomSheetTheme: _bottomSheetLightTheme, + tabBarTheme: _tabBarLightTheme, + dividerTheme: _dividerLightTheme, + backgroundColor: ColorName.lightBackground, + ); + + /// dark `ThemeData` for UI. + static ThemeData get dark => ThemeData( + colorScheme: ColorScheme.fromSwatch( + primarySwatch: ColorName.seedColor, + accentColor: ColorName.darkSecondary, + cardColor: ColorName.darkBackground, + backgroundColor: ColorName.darkBackground, + errorColor: ColorName.darkError, + brightness: Brightness.dark, + ), + appBarTheme: _appBarDarkTheme, + elevatedButtonTheme: _elevatedButtonDarkTheme, + outlinedButtonTheme: _outlinedButtonDarkTheme, + textTheme: _textTheme(isDark: true), + dialogTheme: _dialogDarkTheme, + tooltipTheme: _tooltipDarkTheme, + bottomSheetTheme: _bottomSheetDarkTheme, + tabBarTheme: _tabBarDarkTheme, + dividerTheme: _dividerDarkTheme, + backgroundColor: ColorName.darkBackground, + canvasColor: ColorName.darkBackground, + ); + + /// `ThemeData` for UI for small screens. + static ThemeData get lightSmall => + light.copyWith(textTheme: _smallTextTheme()); + + /// `ThemeData` for UI for medium screens. + static ThemeData get lightMedium => + light.copyWith(textTheme: _smallTextTheme()); + + /// `ThemeData` for UI for large screens. + static ThemeData get lightLarge => + light.copyWith(textTheme: _largeTextTheme()); + + /// `ThemeData` for UI for small screens. + static ThemeData get darkSmall => + dark.copyWith(textTheme: _smallTextTheme(isDark: true)); + + /// `ThemeData` for UI for medium screens. + static ThemeData get darkMedium => + dark.copyWith(textTheme: _smallTextTheme(isDark: true)); + + /// `ThemeData` for UI for large screens. + static ThemeData get darkLarge => + dark.copyWith(textTheme: _largeTextTheme(isDark: true)); + + static TextTheme _textTheme({bool isDark = false}) => TextTheme( + headline1: AppTypography.headline1, + headline2: AppTypography.headline2, + headline3: AppTypography.headline3, + headline4: AppTypography.headline4, + headline5: AppTypography.headline5, + headline6: AppTypography.headline6, + subtitle1: AppTypography.subtitle1, + subtitle2: AppTypography.subtitle2, + bodyText1: AppTypography.bodyText1, + bodyText2: AppTypography.bodyText2, + caption: AppTypography.caption, + overline: AppTypography.overline, + button: AppTypography.button, + ).apply( + bodyColor: + isDark ? ColorName.darkOnBackground : ColorName.lightOnBackground, + displayColor: + isDark ? ColorName.darkOnBackground : ColorName.lightOnBackground, + ); + + static TextTheme _smallTextTheme({bool isDark = false}) => + _textTheme(isDark: isDark).apply(fontSizeFactor: _smallTextScaleFactor); + + static TextTheme _largeTextTheme({bool isDark = false}) => + _textTheme(isDark: isDark).apply(fontSizeFactor: _largeTextScaleFactor); + + static AppBarTheme get _appBarLightTheme => + const AppBarTheme(color: ColorName.lightPrimary); + + static AppBarTheme get _appBarDarkTheme => + const AppBarTheme(color: ColorName.darkSurfaceVariant); + + static ElevatedButtonThemeData get _elevatedButtonLightTheme => + ElevatedButtonThemeData( + style: ElevatedButton.styleFrom( + elevation: 0, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.all(Radius.circular(30)), + ), + primary: ColorName.lightPrimary, + fixedSize: const Size(208, 54), + ), + ); + + static ElevatedButtonThemeData get _elevatedButtonDarkTheme => + ElevatedButtonThemeData( + style: ElevatedButton.styleFrom( + elevation: 0, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.all(Radius.circular(30)), + ), + primary: ColorName.darkPrimary, + fixedSize: const Size(208, 54), + ), + ); + + static OutlinedButtonThemeData get _outlinedButtonLightTheme => + OutlinedButtonThemeData( + style: OutlinedButton.styleFrom( + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.all(Radius.circular(30)), + ), + side: const BorderSide(color: ColorName.lightOutline, width: 2), + primary: ColorName.lightPrimary, + fixedSize: const Size(208, 54), + ), + ); + + static OutlinedButtonThemeData get _outlinedButtonDarkTheme => + OutlinedButtonThemeData( + style: OutlinedButton.styleFrom( + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.all(Radius.circular(30)), + ), + side: const BorderSide(color: ColorName.darkOutline, width: 2), + primary: ColorName.darkPrimary, + fixedSize: const Size(208, 54), + ), + ); + + static TooltipThemeData get _tooltipLightTheme => const TooltipThemeData( + decoration: BoxDecoration( + color: ColorName.lightInverseSurface, + borderRadius: BorderRadius.all(Radius.circular(5)), + ), + padding: EdgeInsets.all(10), + textStyle: TextStyle(color: ColorName.lightOnInverseSurface), + ); + + static TooltipThemeData get _tooltipDarkTheme => const TooltipThemeData( + decoration: BoxDecoration( + color: ColorName.darkInverseSurface, + borderRadius: BorderRadius.all(Radius.circular(5)), + ), + padding: EdgeInsets.all(10), + textStyle: TextStyle(color: ColorName.darkOnInverseSurface), + ); + + static DialogTheme get _dialogLightTheme => DialogTheme( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12), + ), + ); + + static DialogTheme get _dialogDarkTheme => DialogTheme( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12), + ), + ); + + static BottomSheetThemeData get _bottomSheetLightTheme => + const BottomSheetThemeData( + backgroundColor: ColorName.lightBackground, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.vertical(top: Radius.circular(12)), + ), + ); + + static BottomSheetThemeData get _bottomSheetDarkTheme => + const BottomSheetThemeData( + backgroundColor: ColorName.darkBackground, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.vertical(top: Radius.circular(12)), + ), + ); + + static TabBarTheme get _tabBarLightTheme => const TabBarTheme( + indicator: UnderlineTabIndicator( + borderSide: BorderSide( + width: 2, + color: ColorName.lightPrimary, + ), + ), + labelColor: ColorName.lightPrimary, + unselectedLabelColor: ColorName.lightOutline, + indicatorSize: TabBarIndicatorSize.tab, + ); + + static TabBarTheme get _tabBarDarkTheme => const TabBarTheme( + indicator: UnderlineTabIndicator( + borderSide: BorderSide( + width: 2, + color: ColorName.darkPrimary, + ), + ), + labelColor: ColorName.darkPrimary, + unselectedLabelColor: ColorName.darkOutline, + indicatorSize: TabBarIndicatorSize.tab, + ); + + static DividerThemeData get _dividerLightTheme => const DividerThemeData( + space: 0, + thickness: 1, + color: ColorName.lightOutline, + ); + + static DividerThemeData get _dividerDarkTheme => const DividerThemeData( + space: 0, + thickness: 1, + color: ColorName.darkOutline, + ); +} diff --git a/bricks/wyatt_clean_code/__brick__/lib/core/design_system/typography.dart b/bricks/wyatt_clean_code/__brick__/lib/core/design_system/typography.dart new file mode 100644 index 0000000..ce1b241 --- /dev/null +++ b/bricks/wyatt_clean_code/__brick__/lib/core/design_system/typography.dart @@ -0,0 +1,115 @@ +import 'package:flutter/material.dart'; + +abstract class AppFontWeight { + /// FontWeight value of `w900` + static const FontWeight black = FontWeight.w900; + + /// FontWeight value of `w800` + static const FontWeight extraBold = FontWeight.w800; + + /// FontWeight value of `w700` + static const FontWeight bold = FontWeight.w700; + + /// FontWeight value of `w600` + static const FontWeight semiBold = FontWeight.w600; + + /// FontWeight value of `w500` + static const FontWeight medium = FontWeight.w500; + + /// FontWeight value of `w400` + static const FontWeight regular = FontWeight.w400; + + /// FontWeight value of `w300` + static const FontWeight light = FontWeight.w300; + + /// FontWeight value of `w200` + static const FontWeight extraLight = FontWeight.w200; + + /// FontWeight value of `w100` + static const FontWeight thin = FontWeight.w100; +} + +class AppTypography { + static const TextStyle _base = TextStyle( + color: Colors.black, + fontWeight: AppFontWeight.regular, + ); + + /// Headline 1 Text Style + static TextStyle get headline1 => _base.copyWith( + fontSize: 56, + fontWeight: AppFontWeight.medium, + ); + + /// Headline 2 Text Style + static TextStyle get headline2 => _base.copyWith( + fontSize: 30, + fontWeight: AppFontWeight.regular, + ); + + /// Headline 3 Text Style + static TextStyle get headline3 => _base.copyWith( + fontSize: 28, + fontWeight: AppFontWeight.regular, + ); + + /// Headline 4 Text Style + static TextStyle get headline4 => _base.copyWith( + fontSize: 22, + fontWeight: AppFontWeight.bold, + ); + + /// Headline 5 Text Style + static TextStyle get headline5 => _base.copyWith( + fontSize: 20, + fontWeight: AppFontWeight.medium, + ); + + /// Headline 6 Text Style + static TextStyle get headline6 => _base.copyWith( + fontSize: 22, + fontWeight: AppFontWeight.bold, + ); + + /// Subtitle 1 Text Style + static TextStyle get subtitle1 => _base.copyWith( + fontSize: 16, + fontWeight: AppFontWeight.bold, + ); + + /// Subtitle 2 Text Style + static TextStyle get subtitle2 => _base.copyWith( + fontSize: 14, + fontWeight: AppFontWeight.bold, + ); + + /// Body Text 1 Text Style + static TextStyle get bodyText1 => _base.copyWith( + fontSize: 18, + fontWeight: AppFontWeight.medium, + ); + + /// Body Text 2 Text Style (the default) + static TextStyle get bodyText2 => _base.copyWith( + fontSize: 16, + fontWeight: AppFontWeight.regular, + ); + + /// Caption Text Style + static TextStyle get caption => _base.copyWith( + fontSize: 14, + fontWeight: AppFontWeight.regular, + ); + + /// Overline Text Style + static TextStyle get overline => _base.copyWith( + fontSize: 16, + fontWeight: AppFontWeight.regular, + ); + + /// Button Text Style + static TextStyle get button => _base.copyWith( + fontSize: 18, + fontWeight: AppFontWeight.medium, + ); +} diff --git a/bricks/wyatt_clean_code/__brick__/lib/core/enums/.gitkeep b/bricks/wyatt_clean_code/__brick__/lib/core/enums/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/bricks/wyatt_clean_code/__brick__/lib/core/enums/exception_type.dart b/bricks/wyatt_clean_code/__brick__/lib/core/enums/exception_type.dart new file mode 100644 index 0000000..decb960 --- /dev/null +++ b/bricks/wyatt_clean_code/__brick__/lib/core/enums/exception_type.dart @@ -0,0 +1,7 @@ +enum AppExceptionType { + network, + api, + database, + cache, + assertion, +} diff --git a/bricks/wyatt_clean_code/__brick__/lib/core/enums/flavor.dart b/bricks/wyatt_clean_code/__brick__/lib/core/enums/flavor.dart new file mode 100644 index 0000000..2cec6bb --- /dev/null +++ b/bricks/wyatt_clean_code/__brick__/lib/core/enums/flavor.dart @@ -0,0 +1,12 @@ +import 'package:flutter/material.dart'; + +enum Flavor { + development('dev', Colors.red), + staging('stg', Colors.blue), + production('prod', Colors.green); + + final String short; + final Color color; + + const Flavor(this.short, this.color); +} diff --git a/bricks/wyatt_clean_code/__brick__/lib/core/errors/.gitkeep b/bricks/wyatt_clean_code/__brick__/lib/core/errors/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/bricks/wyatt_clean_code/__brick__/lib/core/errors/exceptions.dart b/bricks/wyatt_clean_code/__brick__/lib/core/errors/exceptions.dart new file mode 100644 index 0000000..edda147 --- /dev/null +++ b/bricks/wyatt_clean_code/__brick__/lib/core/errors/exceptions.dart @@ -0,0 +1,29 @@ +import 'package:equatable/equatable.dart'; +import 'package:{{#snakeCase}}{{project_name}}{{/snakeCase}}/core/enums/exception_type.dart'; + +abstract class AppException extends Equatable implements Exception { + final String message; + final AppExceptionType type; + + AppException(this.type, [String? message]) : message = message ?? type.name; + + @override + List get props => [message, type]; + + @override + String toString() => message; +} + +class ClientException extends AppException { + ClientException(super.type, [super.message]); + + @override + String toString() => 'ClientException: ${super.toString()}'; +} + +class ServerException extends AppException { + ServerException(super.type, [super.message]); + + @override + String toString() => 'ServerException: ${super.toString()}'; +} diff --git a/bricks/wyatt_clean_code/__brick__/lib/core/extensions/.gitkeep b/bricks/wyatt_clean_code/__brick__/lib/core/extensions/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/bricks/wyatt_clean_code/__brick__/lib/core/extensions/{{#enable_l10n}}app_localizations_x.dart{{/enable_l10n}} b/bricks/wyatt_clean_code/__brick__/lib/core/extensions/build_context_extension.dart similarity index 83% rename from bricks/wyatt_clean_code/__brick__/lib/core/extensions/{{#enable_l10n}}app_localizations_x.dart{{/enable_l10n}} rename to bricks/wyatt_clean_code/__brick__/lib/core/extensions/build_context_extension.dart index 17c891b..df68dfe 100644 --- a/bricks/wyatt_clean_code/__brick__/lib/core/extensions/{{#enable_l10n}}app_localizations_x.dart{{/enable_l10n}} +++ b/bricks/wyatt_clean_code/__brick__/lib/core/extensions/build_context_extension.dart @@ -3,6 +3,6 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; export 'package:flutter_gen/gen_l10n/app_localizations.dart'; -extension AppLocalizationsX on BuildContext { +extension BuildContextX on BuildContext { AppLocalizations get l10n => AppLocalizations.of(this); } diff --git a/bricks/wyatt_clean_code/__brick__/lib/core/extensions/num_extension.dart b/bricks/wyatt_clean_code/__brick__/lib/core/extensions/num_extension.dart new file mode 100644 index 0000000..5bf9b90 --- /dev/null +++ b/bricks/wyatt_clean_code/__brick__/lib/core/extensions/num_extension.dart @@ -0,0 +1,9 @@ +import 'package:{{#snakeCase}}{{project_name}}{{/snakeCase}}/core/utils/screen_util.dart'; + +extension NumX on num { + double get w => ScreenUtil().setWidth(this); + + double get h => ScreenUtil().setHeight(this); + + double get sp => ScreenUtil().setSp(this); +} diff --git a/bricks/wyatt_clean_code/__brick__/lib/core/extensions/object_extension.dart b/bricks/wyatt_clean_code/__brick__/lib/core/extensions/object_extension.dart new file mode 100644 index 0000000..5d1be48 --- /dev/null +++ b/bricks/wyatt_clean_code/__brick__/lib/core/extensions/object_extension.dart @@ -0,0 +1,32 @@ +import 'package:logger/logger.dart'; +import 'package:{{#snakeCase}}{{project_name}}{{/snakeCase}}/core/utils/wyatt_printer.dart'; + +extension ObjectX on Object { + void log({Level level = Level.debug, String Function(Object obj)? wrap}) { + final msg = wrap != null ? wrap(this) : this; + WyattPrinter.get().log(level, msg); + } + + /// Log a message at level [Level.verbose]. + void v({String Function(Object obj)? wrap}) => + log(level: Level.verbose, wrap: wrap); + + /// Log a message at level [Level.debug]. + void d({String Function(Object obj)? wrap}) => log(wrap: wrap); + + /// Log a message at level [Level.info]. + void i({String Function(Object obj)? wrap}) => + log(level: Level.info, wrap: wrap); + + /// Log a message at level [Level.warning]. + void w({String Function(Object obj)? wrap}) => + log(level: Level.warning, wrap: wrap); + + /// Log a message at level [Level.error]. + void e({String Function(Object obj)? wrap}) => + log(level: Level.error, wrap: wrap); + + /// Log a message at level [Level.wtf]. + void wtf({String Function(Object obj)? wrap}) => + log(level: Level.wtf, wrap: wrap); +} diff --git a/bricks/wyatt_clean_code/__brick__/lib/core/flavors/flavor_settings.dart b/bricks/wyatt_clean_code/__brick__/lib/core/flavors/flavor_settings.dart new file mode 100644 index 0000000..f1a9e1c --- /dev/null +++ b/bricks/wyatt_clean_code/__brick__/lib/core/flavors/flavor_settings.dart @@ -0,0 +1,64 @@ +import 'package:{{#snakeCase}}{{project_name}}{{/snakeCase}}/core/enums/flavor.dart'; + +class FlavorSettings { + static FlavorSettings? _instance; + + final Flavor flavor; + + // Per flavor settings + String apiKey = ''; + + /// Banner are not display in release mode, whatever this value + bool displayBanner = true; + + FlavorSettings._(this.flavor); + + factory FlavorSettings.development() { + _instance ??= FlavorSettings._(Flavor.development); + if (_instance!.flavor != Flavor.development) { + throw Exception('Flavor already initialized in: ${_instance!.flavor}'); + } + return _instance!; + } + + factory FlavorSettings.staging() { + _instance ??= FlavorSettings._(Flavor.staging); + if (_instance!.flavor != Flavor.staging) { + throw Exception('Flavor already initialized in: ${_instance!.flavor}'); + } + return _instance!; + } + + factory FlavorSettings.production() { + _instance ??= FlavorSettings._(Flavor.production); + if (_instance!.flavor != Flavor.production) { + throw Exception('Flavor already initialized in: ${_instance!.flavor}'); + } + return _instance!; + } + + /// Returns initialized [FlavorSettings], may throw if not initialized. + static FlavorSettings get() { + if (_instance == null) { + throw Exception('Flavor not initialized!'); + } + return _instance!; + } + + /// To call after `WidgetsFlutterBinding.ensureInitialized()` + /// + /// Here you can config all the settings attributes. + static void init() { + switch (get().flavor) { + case Flavor.development: + _instance!.apiKey = 'example-dev'; + break; + case Flavor.staging: + _instance!.apiKey = 'example-stg'; + break; + case Flavor.production: + _instance!.apiKey = 'example-prod'; + break; + } + } +} diff --git a/bricks/wyatt_clean_code/__brick__/lib/core/mixins/local_data_source.dart b/bricks/wyatt_clean_code/__brick__/lib/core/mixins/local_data_source.dart new file mode 100644 index 0000000..ea9f71b --- /dev/null +++ b/bricks/wyatt_clean_code/__brick__/lib/core/mixins/local_data_source.dart @@ -0,0 +1,6 @@ +import 'package:{{#snakeCase}}{{project_name}}{{/snakeCase}}/domain/data_sources/local/base_local_data_source.dart'; + +mixin LocalDataSource { + /// Offline data source, for debug or cache + Local get localDataSource; +} diff --git a/bricks/wyatt_clean_code/__brick__/lib/core/mixins/remote_data_source.dart b/bricks/wyatt_clean_code/__brick__/lib/core/mixins/remote_data_source.dart new file mode 100644 index 0000000..dad8ccd --- /dev/null +++ b/bricks/wyatt_clean_code/__brick__/lib/core/mixins/remote_data_source.dart @@ -0,0 +1,6 @@ +import 'package:{{#snakeCase}}{{project_name}}{{/snakeCase}}/domain/data_sources/remote/base_remote_data_source.dart'; + +mixin RemoteDataSource { + /// Online data source, to provide data through API + Remote get remoteDataSource; +} diff --git a/bricks/wyatt_clean_code/__brick__/lib/core/resources/app_theme.dart b/bricks/wyatt_clean_code/__brick__/lib/core/resources/app_theme.dart deleted file mode 100644 index 347cde2..0000000 --- a/bricks/wyatt_clean_code/__brick__/lib/core/resources/app_theme.dart +++ /dev/null @@ -1,8 +0,0 @@ -import 'package:{{#snakeCase}}{{project_name}}{{/snakeCase}}/gen/colors.gen.dart'; -import 'package:flutter/material.dart'; - -abstract class AppTheme { - static ThemeData defaultTheme = ThemeData( - primaryColor: ColorName.crimsonRed - ); -} diff --git a/bricks/wyatt_clean_code/__brick__/lib/core/resources/{{#enable_router}}app_router.dart{{/enable_router}} b/bricks/wyatt_clean_code/__brick__/lib/core/resources/{{#enable_router}}app_router.dart{{/enable_router}} deleted file mode 100644 index 36f16da..0000000 --- a/bricks/wyatt_clean_code/__brick__/lib/core/resources/{{#enable_router}}app_router.dart{{/enable_router}} +++ /dev/null @@ -1,28 +0,0 @@ -import 'package:{{project_name.snakeCase()}}/presentation/pages/initial/initial_page.dart'; -import 'package:{{project_name.snakeCase()}}/presentation/pages/counter/counter_page.dart'; -import 'package:go_router/go_router.dart'; -import 'package:flutter/material.dart'; - -abstract class AppRouter { - static const String initial = 'initial'; - static const String counter = 'counter'; - - static final List routes = [ - GoRoute( - path: '/', - name: initial, - pageBuilder: (context, state) => MaterialPage( - key: state.pageKey, - child: const InitialPage(), - ), - ), - GoRoute( - path: '/counter', - name: counter, - pageBuilder: (context, state) => MaterialPage( - key: state.pageKey, - child: const CounterPage(), - ), - ), - ]; -} diff --git a/bricks/wyatt_clean_code/__brick__/lib/core/routes/router.dart b/bricks/wyatt_clean_code/__brick__/lib/core/routes/router.dart new file mode 100644 index 0000000..0cb4ac6 --- /dev/null +++ b/bricks/wyatt_clean_code/__brick__/lib/core/routes/router.dart @@ -0,0 +1,37 @@ +import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; +import 'package:{{#snakeCase}}{{project_name}}{{/snakeCase}}/presentation/features/counter/counter_page.dart'; +import 'package:{{#snakeCase}}{{project_name}}{{/snakeCase}}/presentation/features/initial/initial_page.dart'; + +abstract class AppRouter { + static Page defaultTransition( + BuildContext context, + GoRouterState state, + Widget child, + ) => + MaterialPage( + key: state.pageKey, + child: child, + ); + + static final List routes = [ + GoRoute( + path: '/', + name: InitialPage.pageName, + pageBuilder: (context, state) => defaultTransition( + context, + state, + const InitialPage(), + ), + ), + GoRoute( + path: '/counter', + name: CounterPage.pageName, + pageBuilder: (context, state) => defaultTransition( + context, + state, + const CounterPage(), + ), + ), + ]; +} diff --git a/bricks/wyatt_clean_code/__brick__/lib/core/usecases/usecase.dart b/bricks/wyatt_clean_code/__brick__/lib/core/usecases/usecase.dart new file mode 100644 index 0000000..4dd8ab6 --- /dev/null +++ b/bricks/wyatt_clean_code/__brick__/lib/core/usecases/usecase.dart @@ -0,0 +1,13 @@ +import 'package:equatable/equatable.dart'; +import 'package:{{#snakeCase}}{{project_name}}{{/snakeCase}}/core/errors/exceptions.dart'; +import 'package:wyatt_type_utils/wyatt_type_utils.dart'; + +// ignore: one_member_abstracts +abstract class UseCase { + Future> call(Params params); +} + +class NoParams extends Equatable { + @override + List get props => []; +} diff --git a/bricks/wyatt_clean_code/__brick__/lib/core/utils/app_bloc_observer.dart b/bricks/wyatt_clean_code/__brick__/lib/core/utils/app_bloc_observer.dart index bd22fa9..5680f35 100644 --- a/bricks/wyatt_clean_code/__brick__/lib/core/utils/app_bloc_observer.dart +++ b/bricks/wyatt_clean_code/__brick__/lib/core/utils/app_bloc_observer.dart @@ -1,5 +1,6 @@ -import 'package:bloc/bloc.dart'; -import 'package:flutter/foundation.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:logger/logger.dart'; +import 'package:{{#snakeCase}}{{project_name}}{{/snakeCase}}/core/extensions/object_extension.dart'; class AppBlocObserver extends BlocObserver { final bool printEvent; @@ -7,6 +8,8 @@ class AppBlocObserver extends BlocObserver { final bool printChange; final bool printTransition; + final Logger logger = Logger(printer: SimplePrinter()); + AppBlocObserver({ this.printEvent = true, this.printError = true, @@ -18,14 +21,16 @@ class AppBlocObserver extends BlocObserver { void onEvent(Bloc bloc, Object? event) { super.onEvent(bloc, event); if (printEvent) { - debugPrint(event.toString()); + event?.d(wrap: (obj) => 'onEvent $event'); } } @override void onError(BlocBase bloc, Object error, StackTrace stackTrace) { if (printError) { - debugPrint(error.toString()); + error.e( + wrap: (obj) => 'onError(${bloc.runtimeType}, $obj, $stackTrace)', + ); } super.onError(bloc, error, stackTrace); } @@ -34,7 +39,7 @@ class AppBlocObserver extends BlocObserver { void onChange(BlocBase bloc, Change change) { super.onChange(bloc, change); if (printChange) { - debugPrint(change.toString()); + change.d(wrap: (obj) => 'onChange(${bloc.runtimeType}, $obj)'); } } @@ -45,7 +50,7 @@ class AppBlocObserver extends BlocObserver { ) { super.onTransition(bloc, transition); if (printTransition) { - debugPrint(transition.toString()); + transition.d(wrap: (obj) => 'onTransition $obj'); } } -} \ No newline at end of file +} diff --git a/bricks/wyatt_clean_code/__brick__/lib/core/utils/screen_util.dart b/bricks/wyatt_clean_code/__brick__/lib/core/utils/screen_util.dart new file mode 100644 index 0000000..8f5656a --- /dev/null +++ b/bricks/wyatt_clean_code/__brick__/lib/core/utils/screen_util.dart @@ -0,0 +1,107 @@ +import 'dart:ui'; + +class ScreenUtil { + static late ScreenUtil _instance; + static const int defaultWidth = 414; + static const int defaultHeight = 896; + + /// Size of the phone in UI Design ,px + late num uiWidthPx; + late num uiHeightPx; + + /// allowFontScaling Specifies whether fonts should scale to respect Text + /// Size accessibility settings. The default is false. + late bool allowFontScaling; + + static late double _screenWidth; + static late double _screenHeight; + static late double _pixelRatio; + static late double _statusBarHeight; + static late double _bottomBarHeight; + static late double _textScaleFactor; + + factory ScreenUtil() => _instance; + + ScreenUtil._(); + + static void init({ + num width = defaultWidth, + num height = defaultHeight, + bool allowFontScaling = false, + }) { + _instance = ScreenUtil._(); + _instance.uiWidthPx = width; + _instance.uiHeightPx = height; + _instance.allowFontScaling = allowFontScaling; + _pixelRatio = window.devicePixelRatio; + _screenWidth = window.physicalSize.width; + _screenHeight = window.physicalSize.height; + _statusBarHeight = window.padding.top; + _bottomBarHeight = window.padding.bottom; + _textScaleFactor = window.textScaleFactor; + } + + /// The number of font pixels for each logical pixel. + static double get textScaleFactor => _textScaleFactor; + + /// The size of the media in logical pixels (e.g, the size of the screen). + static double get pixelRatio => _pixelRatio; + + /// The horizontal extent of this size. + static double get screenWidth => _screenWidth / _pixelRatio; + + ///The vertical extent of this size. dp + static double get screenHeight => _screenHeight / _pixelRatio; + + /// The vertical extent of this size. px + static double get screenWidthPx => _screenWidth; + + /// The vertical extent of this size. px + static double get screenHeightPx => _screenHeight; + + /// The offset from the top + static double get statusBarHeight => _statusBarHeight / _pixelRatio; + + /// The offset from the top + static double get statusBarHeightPx => _statusBarHeight; + + /// The offset from the bottom. + static double get bottomBarHeight => _bottomBarHeight; + + /// The ratio of the actual dp to the design draft px + double get scaleWidth => screenWidth / uiWidthPx; + + double get scaleHeight => + (_screenHeight - _statusBarHeight - _bottomBarHeight) / uiHeightPx; + + double get scaleText => scaleWidth; + + /// Width function + /// + /// Adapted to the device width of the UI Design. + /// Height can also be adapted according to this to ensure no deformation , + /// if you want a square + double setWidth(num width) => width * scaleWidth; + + /// Height function + /// + /// Highly adaptable to the device according to UI Design + /// It is recommended to use this method to achieve a high degree + /// of adaptation when it is found that one screen in the UI design + /// does not match the current style effect, or if there is a difference + /// in shape. + double setHeight(num height) => height * scaleHeight; + + /// FontSize function + /// + /// [fontSize] The size of the font on the UI design, in px. + /// [allowFontScaling] + double setSp(num fontSize, {bool allowFontScalingSelf = false}) => + allowFontScalingSelf + ? (allowFontScalingSelf + ? (fontSize * scaleText) + : ((fontSize * scaleText) / _textScaleFactor)) + : (allowFontScaling + ? (fontSize * scaleText) + : ((fontSize * scaleText) / _textScaleFactor)); +} diff --git a/bricks/wyatt_clean_code/__brick__/lib/core/utils/wyatt_printer.dart b/bricks/wyatt_clean_code/__brick__/lib/core/utils/wyatt_printer.dart new file mode 100644 index 0000000..9ceeb38 --- /dev/null +++ b/bricks/wyatt_clean_code/__brick__/lib/core/utils/wyatt_printer.dart @@ -0,0 +1,43 @@ +import 'dart:convert'; + +import 'package:logger/logger.dart'; + +class WyattPrinter extends LogPrinter { + WyattPrinter({this.colors = true}); + + final bool colors; + + static Logger? _instance; + + /// Returns [Logger] instance or create it if not. + static Logger get({bool colors = true}) { + _instance ??= Logger(printer: WyattPrinter(colors: colors)); + return _instance!; + } + + @override + List log(LogEvent event) { + // final classNameStr = (className != null) ? '$className ' : ''; + final messageStr = _stringifyMessage(event.message); + final errorStr = event.error != null ? 'ERROR: ${event.error}' : ''; + return ['${_labelFor(event.level)} $messageStr$errorStr']; + } + + String _labelFor(Level level) { + final prefix = PrettyPrinter.levelEmojis[level]!; + final color = PrettyPrinter.levelColors[level]!; + + return colors ? color(prefix) : prefix; + } + + String _stringifyMessage(dynamic message) { + // ignore: avoid_dynamic_calls + final finalMessage = message is Function ? message() : message; + if (finalMessage is Map || finalMessage is Iterable) { + const encoder = JsonEncoder.withIndent(null); + return encoder.convert(finalMessage); + } else { + return finalMessage.toString(); + } + } +} diff --git a/bricks/wyatt_clean_code/__brick__/lib/data/data_sources/local/.gitkeep b/bricks/wyatt_clean_code/__brick__/lib/data/data_sources/local/.gitkeep new file mode 100644 index 0000000..f94cb6f --- /dev/null +++ b/bricks/wyatt_clean_code/__brick__/lib/data/data_sources/local/.gitkeep @@ -0,0 +1 @@ +# just to keep empty folder in brick generation \ No newline at end of file diff --git a/bricks/wyatt_clean_code/__brick__/lib/data/data_sources/remote/.gitkeep b/bricks/wyatt_clean_code/__brick__/lib/data/data_sources/remote/.gitkeep new file mode 100644 index 0000000..f94cb6f --- /dev/null +++ b/bricks/wyatt_clean_code/__brick__/lib/data/data_sources/remote/.gitkeep @@ -0,0 +1 @@ +# just to keep empty folder in brick generation \ No newline at end of file diff --git a/bricks/wyatt_clean_code/__brick__/lib/data/models/.gitkeep b/bricks/wyatt_clean_code/__brick__/lib/data/models/.gitkeep index e69de29..f94cb6f 100644 --- a/bricks/wyatt_clean_code/__brick__/lib/data/models/.gitkeep +++ b/bricks/wyatt_clean_code/__brick__/lib/data/models/.gitkeep @@ -0,0 +1 @@ +# just to keep empty folder in brick generation \ No newline at end of file diff --git a/bricks/wyatt_clean_code/__brick__/lib/data/providers/.gitkeep b/bricks/wyatt_clean_code/__brick__/lib/data/providers/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/bricks/wyatt_clean_code/__brick__/lib/data/repositories/.gitkeep b/bricks/wyatt_clean_code/__brick__/lib/data/repositories/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/bricks/wyatt_clean_code/__brick__/lib/data/repositories/counter_repository_impl.dart b/bricks/wyatt_clean_code/__brick__/lib/data/repositories/counter_repository_impl.dart new file mode 100644 index 0000000..d6a5453 --- /dev/null +++ b/bricks/wyatt_clean_code/__brick__/lib/data/repositories/counter_repository_impl.dart @@ -0,0 +1,24 @@ +import 'package:{{#snakeCase}}{{project_name}}{{/snakeCase}}/core/enums/exception_type.dart'; +import 'package:{{#snakeCase}}{{project_name}}{{/snakeCase}}/core/errors/exceptions.dart'; +import 'package:{{#snakeCase}}{{project_name}}{{/snakeCase}}/domain/repositories/counter_repository.dart'; +import 'package:wyatt_type_utils/wyatt_type_utils.dart'; + +class CounterRepositoryImpl implements CounterRepository { + Result _check(int value) => + Result.conditionalLazy( + value >= 0, + () => value, + () => ClientException( + AppExceptionType.assertion, + "Counter can't be negative!", + ), + ); + + @override + Future> decrement(int newState) async => + _check(newState); + + @override + Future> increment(int newState) async => + _check(newState); +} diff --git a/bricks/wyatt_clean_code/__brick__/lib/domain/data_sources/base_data_source.dart b/bricks/wyatt_clean_code/__brick__/lib/domain/data_sources/base_data_source.dart new file mode 100644 index 0000000..05f1202 --- /dev/null +++ b/bricks/wyatt_clean_code/__brick__/lib/domain/data_sources/base_data_source.dart @@ -0,0 +1 @@ +abstract class BaseDataSource {} diff --git a/bricks/wyatt_clean_code/__brick__/lib/domain/data_sources/local/base_local_data_source.dart b/bricks/wyatt_clean_code/__brick__/lib/domain/data_sources/local/base_local_data_source.dart new file mode 100644 index 0000000..05473f8 --- /dev/null +++ b/bricks/wyatt_clean_code/__brick__/lib/domain/data_sources/local/base_local_data_source.dart @@ -0,0 +1,3 @@ +import 'package:{{#snakeCase}}{{project_name}}{{/snakeCase}}/domain/data_sources/base_data_source.dart'; + +abstract class BaseLocalDataSource extends BaseDataSource {} diff --git a/bricks/wyatt_clean_code/__brick__/lib/domain/data_sources/remote/base_remote_data_source.dart b/bricks/wyatt_clean_code/__brick__/lib/domain/data_sources/remote/base_remote_data_source.dart new file mode 100644 index 0000000..ffb2f05 --- /dev/null +++ b/bricks/wyatt_clean_code/__brick__/lib/domain/data_sources/remote/base_remote_data_source.dart @@ -0,0 +1,3 @@ +import 'package:{{#snakeCase}}{{project_name}}{{/snakeCase}}/domain/data_sources/base_data_source.dart'; + +abstract class BaseRemoteDataSource extends BaseDataSource {} diff --git a/bricks/wyatt_clean_code/__brick__/lib/domain/entities/.gitkeep b/bricks/wyatt_clean_code/__brick__/lib/domain/entities/.gitkeep index e69de29..f94cb6f 100644 --- a/bricks/wyatt_clean_code/__brick__/lib/domain/entities/.gitkeep +++ b/bricks/wyatt_clean_code/__brick__/lib/domain/entities/.gitkeep @@ -0,0 +1 @@ +# just to keep empty folder in brick generation \ No newline at end of file diff --git a/bricks/wyatt_clean_code/__brick__/lib/domain/repositories/.gitkeep b/bricks/wyatt_clean_code/__brick__/lib/domain/repositories/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/bricks/wyatt_clean_code/__brick__/lib/domain/repositories/base_repository.dart b/bricks/wyatt_clean_code/__brick__/lib/domain/repositories/base_repository.dart new file mode 100644 index 0000000..2b88f48 --- /dev/null +++ b/bricks/wyatt_clean_code/__brick__/lib/domain/repositories/base_repository.dart @@ -0,0 +1 @@ +abstract class BaseRepository {} diff --git a/bricks/wyatt_clean_code/__brick__/lib/domain/repositories/counter_repository.dart b/bricks/wyatt_clean_code/__brick__/lib/domain/repositories/counter_repository.dart new file mode 100644 index 0000000..1db2339 --- /dev/null +++ b/bricks/wyatt_clean_code/__brick__/lib/domain/repositories/counter_repository.dart @@ -0,0 +1,8 @@ +import 'package:{{#snakeCase}}{{project_name}}{{/snakeCase}}/core/errors/exceptions.dart'; +import 'package:{{#snakeCase}}{{project_name}}{{/snakeCase}}/domain/repositories/base_repository.dart'; +import 'package:wyatt_type_utils/wyatt_type_utils.dart'; + +abstract class CounterRepository extends BaseRepository { + Future> increment(int newState); + Future> decrement(int newState); +} diff --git a/bricks/wyatt_clean_code/__brick__/lib/domain/usecases/counter/decrement_counter.dart b/bricks/wyatt_clean_code/__brick__/lib/domain/usecases/counter/decrement_counter.dart new file mode 100644 index 0000000..4a625d7 --- /dev/null +++ b/bricks/wyatt_clean_code/__brick__/lib/domain/usecases/counter/decrement_counter.dart @@ -0,0 +1,16 @@ +import 'package:{{#snakeCase}}{{project_name}}{{/snakeCase}}/core/errors/exceptions.dart'; +import 'package:{{#snakeCase}}{{project_name}}{{/snakeCase}}/core/usecases/usecase.dart'; +import 'package:{{#snakeCase}}{{project_name}}{{/snakeCase}}/domain/repositories/counter_repository.dart'; +import 'package:wyatt_type_utils/wyatt_type_utils.dart'; + +class DecrementCounter extends UseCase { + final CounterRepository counterRepository; + + DecrementCounter({ + required this.counterRepository, + }); + + @override + Future> call(int params) async => + counterRepository.decrement(params); +} diff --git a/bricks/wyatt_clean_code/__brick__/lib/domain/usecases/counter/increment_counter.dart b/bricks/wyatt_clean_code/__brick__/lib/domain/usecases/counter/increment_counter.dart new file mode 100644 index 0000000..862eed8 --- /dev/null +++ b/bricks/wyatt_clean_code/__brick__/lib/domain/usecases/counter/increment_counter.dart @@ -0,0 +1,16 @@ +import 'package:{{#snakeCase}}{{project_name}}{{/snakeCase}}/core/errors/exceptions.dart'; +import 'package:{{#snakeCase}}{{project_name}}{{/snakeCase}}/core/usecases/usecase.dart'; +import 'package:{{#snakeCase}}{{project_name}}{{/snakeCase}}/domain/repositories/counter_repository.dart'; +import 'package:wyatt_type_utils/wyatt_type_utils.dart'; + +class IncrementCounter extends UseCase { + final CounterRepository counterRepository; + + IncrementCounter({ + required this.counterRepository, + }); + + @override + Future> call(int params) async => + counterRepository.increment(params); +} diff --git a/bricks/wyatt_clean_code/__brick__/lib/gen/assets.gen.dart b/bricks/wyatt_clean_code/__brick__/lib/gen/assets.gen.dart new file mode 100644 index 0000000..00c169e --- /dev/null +++ b/bricks/wyatt_clean_code/__brick__/lib/gen/assets.gen.dart @@ -0,0 +1,87 @@ +/// GENERATED CODE - DO NOT MODIFY BY HAND +/// ***************************************************** +/// FlutterGen +/// ***************************************************** + +// coverage:ignore-file +// ignore_for_file: type=lint +// ignore_for_file: directives_ordering,unnecessary_import + +import 'package:flutter/widgets.dart'; + +class $AssetsImagesGen { + const $AssetsImagesGen(); + + /// File path: assets/images/wyatt-studio-logo.png + AssetGenImage get wyattStudioLogo => + const AssetGenImage('assets/images/wyatt-studio-logo.png'); +} + +class Assets { + Assets._(); + + static const $AssetsImagesGen images = $AssetsImagesGen(); +} + +class AssetGenImage { + const AssetGenImage(this._assetName); + + final String _assetName; + + Image image({ + Key? key, + AssetBundle? bundle, + ImageFrameBuilder? frameBuilder, + ImageErrorWidgetBuilder? errorBuilder, + String? semanticLabel, + bool excludeFromSemantics = false, + double? scale, + double? width, + double? height, + Color? color, + Animation? opacity, + BlendMode? colorBlendMode, + BoxFit? fit, + AlignmentGeometry alignment = Alignment.center, + ImageRepeat repeat = ImageRepeat.noRepeat, + Rect? centerSlice, + bool matchTextDirection = false, + bool gaplessPlayback = false, + bool isAntiAlias = false, + String? package, + FilterQuality filterQuality = FilterQuality.low, + int? cacheWidth, + int? cacheHeight, + }) { + return Image.asset( + _assetName, + key: key, + bundle: bundle, + frameBuilder: frameBuilder, + errorBuilder: errorBuilder, + semanticLabel: semanticLabel, + excludeFromSemantics: excludeFromSemantics, + scale: scale, + width: width, + height: height, + color: color, + opacity: opacity, + colorBlendMode: colorBlendMode, + fit: fit, + alignment: alignment, + repeat: repeat, + centerSlice: centerSlice, + matchTextDirection: matchTextDirection, + gaplessPlayback: gaplessPlayback, + isAntiAlias: isAntiAlias, + package: package, + filterQuality: filterQuality, + cacheWidth: cacheWidth, + cacheHeight: cacheHeight, + ); + } + + String get path => _assetName; + + String get keyName => _assetName; +} diff --git a/bricks/wyatt_clean_code/__brick__/lib/gen/colors.gen.dart b/bricks/wyatt_clean_code/__brick__/lib/gen/colors.gen.dart new file mode 100644 index 0000000..5693c5c --- /dev/null +++ b/bricks/wyatt_clean_code/__brick__/lib/gen/colors.gen.dart @@ -0,0 +1,195 @@ +/// GENERATED CODE - DO NOT MODIFY BY HAND +/// ***************************************************** +/// FlutterGen +/// ***************************************************** + +// coverage:ignore-file +// ignore_for_file: type=lint +// ignore_for_file: directives_ordering,unnecessary_import + +import 'package:flutter/painting.dart'; +import 'package:flutter/material.dart'; + +class ColorName { + ColorName._(); + + /// Color: #FF1B1B1B + static const Color darkBackground = Color(0xFF1B1B1B); + + /// Color: #FFFFB4A9 + static const Color darkError = Color(0xFFFFB4A9); + + /// Color: #FF930006 + static const Color darkErrorContainer = Color(0xFF930006); + + /// Color: #FF0061A6 + static const Color darkInversePrimary = Color(0xFF0061A6); + + /// Color: #FFE2E2E6 + static const Color darkInverseSurface = Color(0xFFE2E2E6); + + /// Color: #FFE2E2E6 + static const Color darkOnBackground = Color(0xFFE2E2E6); + + /// Color: #FF680003 + static const Color darkOnError = Color(0xFF680003); + + /// Color: #FFFFB4A9 + static const Color darkOnErrorContainer = Color(0xFFFFB4A9); + + /// Color: #FF2F3033 + static const Color darkOnInverseSurface = Color(0xFF2F3033); + + /// Color: #FF00325A + static const Color darkOnPrimary = Color(0xFF00325A); + + /// Color: #FFD0E4FF + static const Color darkOnPrimaryContainer = Color(0xFFD0E4FF); + + /// Color: #FF253140 + static const Color darkOnSecondary = Color(0xFF253140); + + /// Color: #FFD6E3F7 + static const Color darkOnSecondaryContainer = Color(0xFFD6E3F7); + + /// Color: #FFE2E2E6 + static const Color darkOnSurface = Color(0xFFE2E2E6); + + /// Color: #FFC3C7D0 + static const Color darkOnSurfaceVariant = Color(0xFFC3C7D0); + + /// Color: #FF8D9199 + static const Color darkOutline = Color(0xFF8D9199); + + /// Color: #FF9CCAFF + static const Color darkPrimary = Color(0xFF9CCAFF); + + /// Color: #FF00497F + static const Color darkPrimaryContainer = Color(0xFF00497F); + + /// Color: #FFBBC8DB + static const Color darkSecondary = Color(0xFFBBC8DB); + + /// Color: #FF3C4858 + static const Color darkSecondaryContainer = Color(0xFF3C4858); + + /// Color: #FF000000 + static const Color darkShadow = Color(0xFF000000); + + /// Color: #FF1B1B1B + static const Color darkSurface = Color(0xFF1B1B1B); + + /// Color: #FF42474E + static const Color darkSurfaceVariant = Color(0xFF42474E); + + /// Color: #FFFDFCFF + static const Color lightBackground = Color(0xFFFDFCFF); + + /// Color: #FFBA1B1B + static const Color lightError = Color(0xFFBA1B1B); + + /// Color: #FFFFDAD4 + static const Color lightErrorContainer = Color(0xFFFFDAD4); + + /// Color: #FF9CCAFF + static const Color lightInversePrimary = Color(0xFF9CCAFF); + + /// Color: #FF2F3033 + static const Color lightInverseSurface = Color(0xFF2F3033); + + /// Color: #FF1B1B1B + static const Color lightOnBackground = Color(0xFF1B1B1B); + + /// Color: #FFFFFFFF + static const Color lightOnError = Color(0xFFFFFFFF); + + /// Color: #FF410001 + static const Color lightOnErrorContainer = Color(0xFF410001); + + /// Color: #FFF1F0F4 + static const Color lightOnInverseSurface = Color(0xFFF1F0F4); + + /// Color: #FFFFFFFF + static const Color lightOnPrimary = Color(0xFFFFFFFF); + + /// Color: #FF001D36 + static const Color lightOnPrimaryContainer = Color(0xFF001D36); + + /// Color: #FFFFFFFF + static const Color lightOnSecondary = Color(0xFFFFFFFF); + + /// Color: #FF101C2B + static const Color lightOnSecondaryContainer = Color(0xFF101C2B); + + /// Color: #FF1B1B1B + static const Color lightOnSurface = Color(0xFF1B1B1B); + + /// Color: #FF42474E + static const Color lightOnSurfaceVariant = Color(0xFF42474E); + + /// Color: #FF73777F + static const Color lightOutline = Color(0xFF73777F); + + /// Color: #FF0061A6 + static const Color lightPrimary = Color(0xFF0061A6); + + /// Color: #FFD0E4FF + static const Color lightPrimaryContainer = Color(0xFFD0E4FF); + + /// Color: #FF535F70 + static const Color lightSecondary = Color(0xFF535F70); + + /// Color: #FFD6E3F7 + static const Color lightSecondaryContainer = Color(0xFFD6E3F7); + + /// Color: #FF000000 + static const Color lightShadow = Color(0xFF000000); + + /// Color: #FFFDFCFF + static const Color lightSurface = Color(0xFFFDFCFF); + + /// Color: #FFDFE2EB + static const Color lightSurfaceVariant = Color(0xFFDFE2EB); + + /// MaterialColor: + /// 50: #FFFFE412FE + /// 100: #FFFFBC2DFB + /// 200: #FFFF904BF9 + /// 300: #FFFF6469F7 + /// 400: #FFFF428075 + /// 500: #FFFF2196F3 + /// 600: #FFFF1DC2114 + /// 700: #FFFF181B382C + /// 800: #FFFF14296C06 + /// 900: #FFFF0B432A01 + static const MaterialColor seedColor = MaterialColor( + 0xFFFF2196F3, + { + 50: Color(0xFFFFE412FE), + 100: Color(0xFFFFBC2DFB), + 200: Color(0xFFFF904BF9), + 300: Color(0xFFFF6469F7), + 400: Color(0xFFFF428075), + 500: Color(0xFFFF2196F3), + 600: Color(0xFFFF1DC2114), + 700: Color(0xFFFF181B382C), + 800: Color(0xFFFF14296C06), + 900: Color(0xFFFF0B432A01), + }, + ); + + /// MaterialAccentColor: + /// 100: #FFFFFFFF + /// 200: #FFFFFFFF + /// 400: #FFFFFFFF + /// 700: #FFFFFFFF + static const MaterialAccentColor seedColorAccent = MaterialAccentColor( + 0xFFFFFFFF, + { + 100: Color(0xFFFFFFFF), + 200: Color(0xFFFFFFFF), + 400: Color(0xFFFFFFFF), + 700: Color(0xFFFFFFFF), + }, + ); +} diff --git a/bricks/wyatt_clean_code/__brick__/lib/main.dart b/bricks/wyatt_clean_code/__brick__/lib/main.dart deleted file mode 100644 index 61831dd..0000000 --- a/bricks/wyatt_clean_code/__brick__/lib/main.dart +++ /dev/null @@ -1,18 +0,0 @@ -import 'package:{{project_name.snakeCase()}}/app.dart'; -import 'package:{{project_name.snakeCase()}}/core/utils/app_bloc_observer.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -{{#enable_router}}import 'package:go_router/go_router.dart';{{/enable_router}} - -Future main() async { - WidgetsFlutterBinding.ensureInitialized(); - - {{#enable_router}}GoRouter.setUrlPathStrategy(UrlPathStrategy.path);{{/enable_router}} - - BlocOverrides.runZoned( - () => runApp( - const App(), - ), - blocObserver: AppBlocObserver(), - ); -} diff --git a/bricks/wyatt_clean_code/__brick__/lib/main_development.dart b/bricks/wyatt_clean_code/__brick__/lib/main_development.dart new file mode 100644 index 0000000..e665c91 --- /dev/null +++ b/bricks/wyatt_clean_code/__brick__/lib/main_development.dart @@ -0,0 +1,8 @@ +import 'package:{{#snakeCase}}{{project_name}}{{/snakeCase}}/bootstrap.dart'; +import 'package:{{#snakeCase}}{{project_name}}{{/snakeCase}}/core/flavors/flavor_settings.dart'; +import 'package:{{#snakeCase}}{{project_name}}{{/snakeCase}}/presentation/features/app/app.dart'; + +void main(List args) { + FlavorSettings.development(); + bootstrap(App.new); +} diff --git a/bricks/wyatt_clean_code/__brick__/lib/main_production.dart b/bricks/wyatt_clean_code/__brick__/lib/main_production.dart new file mode 100644 index 0000000..cb80a75 --- /dev/null +++ b/bricks/wyatt_clean_code/__brick__/lib/main_production.dart @@ -0,0 +1,8 @@ +import 'package:{{#snakeCase}}{{project_name}}{{/snakeCase}}/bootstrap.dart'; +import 'package:{{#snakeCase}}{{project_name}}{{/snakeCase}}/core/flavors/flavor_settings.dart'; +import 'package:{{#snakeCase}}{{project_name}}{{/snakeCase}}/presentation/features/app/app.dart'; + +void main(List args) { + FlavorSettings.production(); + bootstrap(App.new); +} diff --git a/bricks/wyatt_clean_code/__brick__/lib/main_staging.dart b/bricks/wyatt_clean_code/__brick__/lib/main_staging.dart new file mode 100644 index 0000000..6be7658 --- /dev/null +++ b/bricks/wyatt_clean_code/__brick__/lib/main_staging.dart @@ -0,0 +1,8 @@ +import 'package:{{#snakeCase}}{{project_name}}{{/snakeCase}}/bootstrap.dart'; +import 'package:{{#snakeCase}}{{project_name}}{{/snakeCase}}/core/flavors/flavor_settings.dart'; +import 'package:{{#snakeCase}}{{project_name}}{{/snakeCase}}/presentation/features/app/app.dart'; + +void main(List args) { + FlavorSettings.staging(); + bootstrap(App.new); +} diff --git a/bricks/wyatt_clean_code/__brick__/lib/presentation/bloc/counter_cubit/counter_cubit.dart b/bricks/wyatt_clean_code/__brick__/lib/presentation/bloc/counter_cubit/counter_cubit.dart deleted file mode 100644 index 70bd952..0000000 --- a/bricks/wyatt_clean_code/__brick__/lib/presentation/bloc/counter_cubit/counter_cubit.dart +++ /dev/null @@ -1,8 +0,0 @@ -import 'package:bloc/bloc.dart'; - -class CounterCubit extends Cubit { - CounterCubit() : super(0); - - void increment() => emit(state + 1); - void decrement() => emit(state - 1); -} diff --git a/bricks/wyatt_clean_code/__brick__/lib/presentation/features/app/app.dart b/bricks/wyatt_clean_code/__brick__/lib/presentation/features/app/app.dart new file mode 100644 index 0000000..67811c0 --- /dev/null +++ b/bricks/wyatt_clean_code/__brick__/lib/presentation/features/app/app.dart @@ -0,0 +1,71 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_localizations/flutter_localizations.dart'; +import 'package:go_router/go_router.dart'; +import 'package:{{#snakeCase}}{{project_name}}{{/snakeCase}}/core/design_system/theme.dart'; +import 'package:{{#snakeCase}}{{project_name}}{{/snakeCase}}/core/extensions/build_context_extension.dart'; +import 'package:{{#snakeCase}}{{project_name}}{{/snakeCase}}/core/flavors/flavor_settings.dart'; +import 'package:{{#snakeCase}}{{project_name}}{{/snakeCase}}/core/routes/router.dart'; +import 'package:{{#snakeCase}}{{project_name}}{{/snakeCase}}/core/utils/screen_util.dart'; +import 'package:{{#snakeCase}}{{project_name}}{{/snakeCase}}/data/repositories/counter_repository_impl.dart'; +import 'package:{{#snakeCase}}{{project_name}}{{/snakeCase}}/domain/repositories/counter_repository.dart'; + +class App extends StatelessWidget { + App({super.key}); + + final GoRouter _router = GoRouter( + initialLocation: '/', + routes: AppRouter.routes, + debugLogDiagnostics: true, + errorBuilder: (_, __) => const ColoredBox( + color: Colors.red, + ), + ); + + Widget _bannerFlavor(Widget child) { + final flavorInstance = FlavorSettings.get(); + if (flavorInstance.displayBanner && !kReleaseMode) { + return Directionality( + textDirection: TextDirection.ltr, + child: Banner( + location: BannerLocation.topEnd, + message: flavorInstance.flavor.short, + color: flavorInstance.flavor.color, + child: child, + ), + ); + } + return child; + } + + @override + Widget build(BuildContext context) { + ScreenUtil.init(); + return MultiRepositoryProvider( + providers: [ + RepositoryProvider( + lazy: true, + create: (context) => CounterRepositoryImpl(), + ), + ], + child: _bannerFlavor( + MaterialApp.router( + title: '{{#titleCase}}{{project_name}}{{/titleCase}}', + theme: AppTheme.light, + debugShowCheckedModeBanner: false, + routerDelegate: _router.routerDelegate, + routeInformationParser: _router.routeInformationParser, + routeInformationProvider: _router.routeInformationProvider, + localizationsDelegates: const [ + AppLocalizations.delegate, + GlobalMaterialLocalizations.delegate, + GlobalWidgetsLocalizations.delegate, + GlobalCupertinoLocalizations.delegate, + ], + supportedLocales: AppLocalizations.supportedLocales, + ), + ), + ); + } +} diff --git a/bricks/wyatt_clean_code/__brick__/lib/presentation/features/counter/blocs/counter_cubit.dart b/bricks/wyatt_clean_code/__brick__/lib/presentation/features/counter/blocs/counter_cubit.dart new file mode 100644 index 0000000..ee727f6 --- /dev/null +++ b/bricks/wyatt_clean_code/__brick__/lib/presentation/features/counter/blocs/counter_cubit.dart @@ -0,0 +1,39 @@ +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:{{#snakeCase}}{{project_name}}{{/snakeCase}}/domain/usecases/counter/decrement_counter.dart'; +import 'package:{{#snakeCase}}{{project_name}}{{/snakeCase}}/domain/usecases/counter/increment_counter.dart'; + +class CounterCubit extends Cubit { + final IncrementCounter _incrementCounter; + final DecrementCounter _decrementCounter; + + CounterCubit({ + required IncrementCounter incrementCounter, + required DecrementCounter decrementCounter, + }) : _incrementCounter = incrementCounter, + _decrementCounter = decrementCounter, + super(0); + + Future increment({int by = 1}) async { + // Use `.call(...)` to get documentation, but we can + // also directly use `(...)` + final response = await _incrementCounter.call(state + by); + emit( + response.fold( + (value) => value, + (error) => state, + ), + ); + } + + Future decrement({int by = 1}) async { + // Use `.call(...)` to get documentation, but we can + // also directly use `(...)` + final response = await _decrementCounter.call(state - by); + emit( + response.fold( + (value) => value, + (error) => state, + ), + ); + } +} diff --git a/bricks/wyatt_clean_code/__brick__/lib/presentation/features/counter/counter_page.dart b/bricks/wyatt_clean_code/__brick__/lib/presentation/features/counter/counter_page.dart new file mode 100644 index 0000000..e13e08d --- /dev/null +++ b/bricks/wyatt_clean_code/__brick__/lib/presentation/features/counter/counter_page.dart @@ -0,0 +1,11 @@ +import 'package:flutter/material.dart'; +import 'package:{{#snakeCase}}{{project_name}}{{/snakeCase}}/presentation/features/counter/state_management/counter_page_provider.dart'; + +class CounterPage extends StatelessWidget { + const CounterPage({super.key}); + + static const String pageName = 'counter'; + + @override + Widget build(BuildContext context) => const CounterPageProvider(); +} diff --git a/bricks/wyatt_clean_code/__brick__/lib/presentation/features/counter/state_management/counter_page_provider.dart b/bricks/wyatt_clean_code/__brick__/lib/presentation/features/counter/state_management/counter_page_provider.dart new file mode 100644 index 0000000..d7e8019 --- /dev/null +++ b/bricks/wyatt_clean_code/__brick__/lib/presentation/features/counter/state_management/counter_page_provider.dart @@ -0,0 +1,31 @@ +import 'package:flutter/material.dart'; +import 'package:wyatt_bloc_helper/wyatt_bloc_helper.dart'; +import 'package:{{#snakeCase}}{{project_name}}{{/snakeCase}}/domain/repositories/counter_repository.dart'; +import 'package:{{#snakeCase}}{{project_name}}{{/snakeCase}}/domain/usecases/counter/decrement_counter.dart'; +import 'package:{{#snakeCase}}{{project_name}}{{/snakeCase}}/domain/usecases/counter/increment_counter.dart'; +import 'package:{{#snakeCase}}{{project_name}}{{/snakeCase}}/presentation/features/counter/blocs/counter_cubit.dart'; +import 'package:{{#snakeCase}}{{project_name}}{{/snakeCase}}/presentation/features/counter/state_management/counter_text_consumer.dart'; +import 'package:{{#snakeCase}}{{project_name}}{{/snakeCase}}/presentation/features/counter/widgets/counter_base.dart'; + +class CounterPageProvider extends CubitProviderScreen { + const CounterPageProvider({super.key}); + + @override + CounterCubit create(BuildContext context) => CounterCubit( + decrementCounter: DecrementCounter( + counterRepository: repo(context), + ), + incrementCounter: IncrementCounter( + counterRepository: repo(context), + ), + ); + + @override + Widget builder(BuildContext context) => CounterBase( + fabIncrement: () => bloc(context).increment(), + fabIncrementBy10: () => bloc(context).increment(by: 10), + fabDecrement: () => bloc(context).decrement(), + fabDecrementBy10: () => bloc(context).decrement(by: 10), + child: const CounterTextConsumer(), + ); +} diff --git a/bricks/wyatt_clean_code/__brick__/lib/presentation/features/counter/state_management/counter_text_consumer.dart b/bricks/wyatt_clean_code/__brick__/lib/presentation/features/counter/state_management/counter_text_consumer.dart new file mode 100644 index 0000000..0c42db3 --- /dev/null +++ b/bricks/wyatt_clean_code/__brick__/lib/presentation/features/counter/state_management/counter_text_consumer.dart @@ -0,0 +1,11 @@ +import 'package:flutter/widgets.dart'; +import 'package:wyatt_bloc_helper/wyatt_bloc_helper.dart'; +import 'package:{{#snakeCase}}{{project_name}}{{/snakeCase}}/presentation/features/counter/blocs/counter_cubit.dart'; +import 'package:{{#snakeCase}}{{project_name}}{{/snakeCase}}/presentation/features/counter/widgets/counter_text.dart'; + +class CounterTextConsumer extends CubitConsumerScreen { + const CounterTextConsumer({super.key}); + + @override + Widget onBuild(BuildContext context, int state) => CounterText(count: state); +} diff --git a/bricks/wyatt_clean_code/__brick__/lib/presentation/features/counter/widgets/counter_base.dart b/bricks/wyatt_clean_code/__brick__/lib/presentation/features/counter/widgets/counter_base.dart new file mode 100644 index 0000000..a392410 --- /dev/null +++ b/bricks/wyatt_clean_code/__brick__/lib/presentation/features/counter/widgets/counter_base.dart @@ -0,0 +1,54 @@ +import 'package:flutter/material.dart'; +import 'package:{{#snakeCase}}{{project_name}}{{/snakeCase}}/core/extensions/build_context_extension.dart'; +import 'package:{{#snakeCase}}{{project_name}}{{/snakeCase}}/presentation/shared/layouts/app_default_scaffold.dart'; + +class CounterBase extends StatelessWidget { + const CounterBase({ + required this.child, + this.fabIncrement, + this.fabIncrementBy10, + this.fabDecrement, + this.fabDecrementBy10, + super.key, + }); + + final void Function()? fabIncrement; + final void Function()? fabIncrementBy10; + final void Function()? fabDecrement; + final void Function()? fabDecrementBy10; + + final Widget child; + + @override + Widget build(BuildContext context) => AppDefaultScaffold( + title: Text(context.l10n.counterAppBarTitle), + body: Center( + child: child, + ), + fabChildren: [ + FloatingActionButton( + heroTag: 'increment_tag', + onPressed: fabIncrement, + child: const Icon(Icons.add), + ), + const SizedBox(height: 8), + FloatingActionButton( + heroTag: 'increment_10_tag', + onPressed: fabIncrementBy10, + child: const Text('+10'), + ), + const SizedBox(height: 8), + FloatingActionButton( + heroTag: 'decrement_tag', + onPressed: fabDecrement, + child: const Icon(Icons.remove), + ), + const SizedBox(height: 8), + FloatingActionButton( + heroTag: 'decrement_10_tag', + onPressed: fabDecrementBy10, + child: const Text('-10'), + ), + ], + ); +} diff --git a/bricks/wyatt_clean_code/__brick__/lib/presentation/features/counter/widgets/counter_text.dart b/bricks/wyatt_clean_code/__brick__/lib/presentation/features/counter/widgets/counter_text.dart new file mode 100644 index 0000000..fee1643 --- /dev/null +++ b/bricks/wyatt_clean_code/__brick__/lib/presentation/features/counter/widgets/counter_text.dart @@ -0,0 +1,18 @@ +import 'package:flutter/material.dart'; +import 'package:{{#snakeCase}}{{project_name}}{{/snakeCase}}/core/extensions/build_context_extension.dart'; + +class CounterText extends StatelessWidget { + const CounterText({ + required this.count, + super.key, + }); + + final int count; + + @override + Widget build(BuildContext context) => Text( + context.l10n.youHavePushed(count), + textAlign: TextAlign.center, + style: Theme.of(context).textTheme.headline3, + ); +} diff --git a/bricks/wyatt_clean_code/__brick__/lib/presentation/features/initial/initial_page.dart b/bricks/wyatt_clean_code/__brick__/lib/presentation/features/initial/initial_page.dart new file mode 100644 index 0000000..2e65908 --- /dev/null +++ b/bricks/wyatt_clean_code/__brick__/lib/presentation/features/initial/initial_page.dart @@ -0,0 +1,32 @@ +import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; +import 'package:{{#snakeCase}}{{project_name}}{{/snakeCase}}/core/design_system/sizing.dart'; +import 'package:{{#snakeCase}}{{project_name}}{{/snakeCase}}/core/extensions/build_context_extension.dart'; +import 'package:{{#snakeCase}}{{project_name}}{{/snakeCase}}/core/extensions/num_extension.dart'; +import 'package:{{#snakeCase}}{{project_name}}{{/snakeCase}}/gen/assets.gen.dart'; +import 'package:{{#snakeCase}}{{project_name}}{{/snakeCase}}/presentation/features/counter/counter_page.dart'; +import 'package:{{#snakeCase}}{{project_name}}{{/snakeCase}}/presentation/shared/layouts/app_default_scaffold.dart'; + +class InitialPage extends StatelessWidget { + const InitialPage({super.key}); + + static const String pageName = 'initial'; + + @override + Widget build(BuildContext context) => AppDefaultScaffold( + title: const Text('{{#titleCase}}{{project_name}}{{/titleCase}}'), + body: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Assets.images.wyattStudioLogo.image(width: 150.w), + AppSizing.lGap, + ElevatedButton( + child: Text(context.l10n.goToCounter), + onPressed: () => context.pushNamed(CounterPage.pageName), + ), + ], + ), + ), + ); +} diff --git a/bricks/wyatt_clean_code/__brick__/lib/presentation/pages/counter/counter_page.dart b/bricks/wyatt_clean_code/__brick__/lib/presentation/pages/counter/counter_page.dart deleted file mode 100644 index 91be000..0000000 --- a/bricks/wyatt_clean_code/__brick__/lib/presentation/pages/counter/counter_page.dart +++ /dev/null @@ -1,40 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:{{#snakeCase}}{{project_name}}{{/snakeCase}}/presentation/bloc/counter_cubit/counter_cubit.dart'; -import 'package:{{#snakeCase}}{{project_name}}{{/snakeCase}}/presentation/shared/state_management/counter_state_management.dart'; -{{#enable_l10n}}import 'package:{{project_name.snakeCase()}}/core/extensions/app_localizations_x.dart';{{/enable_l10n}} -import 'package:{{#snakeCase}}{{project_name}}{{/snakeCase}}/presentation/pages/counter/widgets/counter_text.dart'; - -class CounterPage extends StatelessWidget { - const CounterPage({super.key}); - - @override - Widget build(BuildContext context) { - return CounterStateManagement( - builder: (BuildContext context, int state) { - return Scaffold( - {{#enable_l10n}}appBar: AppBar(title: Text(context.l10n.counterAppBarTitle)),{{/enable_l10n}} - {{^enable_l10n}}appBar: AppBar(title: Text('Counter')),{{/enable_l10n}} - body: const Center(child: CounterText()), - floatingActionButton: Column( - mainAxisAlignment: MainAxisAlignment.end, - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - FloatingActionButton( - heroTag: 'increment_tag', - onPressed: () => context.read().increment(), - child: const Icon(Icons.add), - ), - const SizedBox(height: 8), - FloatingActionButton( - heroTag: 'decrement_tag', - onPressed: () => context.read().decrement(), - child: const Icon(Icons.remove), - ), - ], - ), - ); - } - ); - } -} diff --git a/bricks/wyatt_clean_code/__brick__/lib/presentation/pages/counter/widgets/counter_text.dart b/bricks/wyatt_clean_code/__brick__/lib/presentation/pages/counter/widgets/counter_text.dart deleted file mode 100644 index c0e2345..0000000 --- a/bricks/wyatt_clean_code/__brick__/lib/presentation/pages/counter/widgets/counter_text.dart +++ /dev/null @@ -1,14 +0,0 @@ -import 'package:{{#snakeCase}}{{project_name}}{{/snakeCase}}/presentation/bloc/counter_cubit/counter_cubit.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; - -class CounterText extends StatelessWidget { - const CounterText({super.key}); - - @override - Widget build(BuildContext context) { - final theme = Theme.of(context); - final count = context.select((CounterCubit cubit) => cubit.state); - return Text('$count', style: theme.textTheme.headline1); - } -} diff --git a/bricks/wyatt_clean_code/__brick__/lib/presentation/pages/initial/initial_page.dart b/bricks/wyatt_clean_code/__brick__/lib/presentation/pages/initial/initial_page.dart deleted file mode 100644 index 0f7f0b6..0000000 --- a/bricks/wyatt_clean_code/__brick__/lib/presentation/pages/initial/initial_page.dart +++ /dev/null @@ -1,26 +0,0 @@ -import 'package:flutter/material.dart'; -{{#enable_router}}import 'package:go_router/go_router.dart'; -import 'package:{{project_name.snakeCase()}}/core/resources/app_router.dart';{{/enable_router}} -{{^enable_router}}import 'package:{{project_name.snakeCase()}}/presentation/pages/counter/counter_page.dart';{{/enable_router}} -{{#enable_l10n}}import 'package:{{project_name.snakeCase()}}/core/extensions/app_localizations_x.dart';{{/enable_l10n}} - -class InitialPage extends StatelessWidget { - const InitialPage({super.key}); - - @override - Widget build(BuildContext context) { - return Scaffold( - body: Column( - children: [ - const Center(child: Text('{{project_name.titleCase()}}'),), - Center(child: ElevatedButton( - {{#enable_router}}onPressed: () => context.goNamed(AppRouter.counter),{{/enable_router}} - {{^enable_router}}onPressed: () => Navigator.of(context).push(MaterialPageRoute(builder: (context) => CounterPage())),{{/enable_router}} - {{#enable_l10n}}child: Text(context.l10n.goToCounter),{{/enable_l10n}} - {{^enable_l10n}}child: Text('Go to counter'),{{/enable_l10n}} - ),) - ], - ), - ); - } -} diff --git a/bricks/wyatt_clean_code/__brick__/lib/presentation/shared/layouts/.gitkeep b/bricks/wyatt_clean_code/__brick__/lib/presentation/shared/layouts/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/bricks/wyatt_clean_code/__brick__/lib/presentation/shared/layouts/app_default_scaffold.dart b/bricks/wyatt_clean_code/__brick__/lib/presentation/shared/layouts/app_default_scaffold.dart new file mode 100644 index 0000000..1d21aa1 --- /dev/null +++ b/bricks/wyatt_clean_code/__brick__/lib/presentation/shared/layouts/app_default_scaffold.dart @@ -0,0 +1,27 @@ +import 'package:flutter/material.dart'; + +class AppDefaultScaffold extends StatelessWidget { + const AppDefaultScaffold({ + required this.body, + this.title, + this.fabChildren, + super.key, + }); + + final Widget? title; + final Widget body; + final List? fabChildren; + + @override + Widget build(BuildContext context) => Scaffold( + appBar: AppBar(title: title), + body: body, + floatingActionButton: (fabChildren?.isNotEmpty ?? false) + ? Column( + mainAxisAlignment: MainAxisAlignment.end, + crossAxisAlignment: CrossAxisAlignment.end, + children: fabChildren!, + ) + : null, + ); +} diff --git a/bricks/wyatt_clean_code/__brick__/lib/presentation/shared/state_management/.gitkeep b/bricks/wyatt_clean_code/__brick__/lib/presentation/shared/state_management/.gitkeep new file mode 100644 index 0000000..f94cb6f --- /dev/null +++ b/bricks/wyatt_clean_code/__brick__/lib/presentation/shared/state_management/.gitkeep @@ -0,0 +1 @@ +# just to keep empty folder in brick generation \ No newline at end of file diff --git a/bricks/wyatt_clean_code/__brick__/lib/presentation/shared/state_management/counter_state_management.dart b/bricks/wyatt_clean_code/__brick__/lib/presentation/shared/state_management/counter_state_management.dart deleted file mode 100644 index 56abbbc..0000000 --- a/bricks/wyatt_clean_code/__brick__/lib/presentation/shared/state_management/counter_state_management.dart +++ /dev/null @@ -1,26 +0,0 @@ -import 'package:{{#snakeCase}}{{project_name}}{{/snakeCase}}/presentation/bloc/counter_cubit/counter_cubit.dart'; -import 'package:flutter/material.dart'; -import 'package:wyatt_bloc_helper/wyatt_bloc_helper.dart'; - -class CounterStateManagement extends CubitScreen { - const CounterStateManagement({ - super.key, - this.init, - required this.builder, - }); - - final void Function(CounterCubit cubit)? init; - final Widget Function(BuildContext context, int state) builder; - - @override - CounterCubit create(BuildContext context) { - final cubit = CounterCubit(); - init?.call(cubit); - return cubit; - } - - @override - Widget onBuild(BuildContext context, int state) { - return builder.call(context, state); - } -} diff --git a/bricks/wyatt_clean_code/__brick__/lib/presentation/shared/widgets/.gitkeep b/bricks/wyatt_clean_code/__brick__/lib/presentation/shared/widgets/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/bricks/wyatt_clean_code/__brick__/lib/widget_tree.dart b/bricks/wyatt_clean_code/__brick__/lib/widget_tree.dart deleted file mode 100644 index 2d30095..0000000 --- a/bricks/wyatt_clean_code/__brick__/lib/widget_tree.dart +++ /dev/null @@ -1,63 +0,0 @@ -{{#enable_router}}import 'package:{{project_name.snakeCase()}}/core/resources/app_router.dart'; -import 'package:go_router/go_router.dart';{{/enable_router}} -import 'package:{{project_name.snakeCase()}}/core/resources/app_theme.dart'; -{{#enable_l10n}}import 'package:flutter_localizations/flutter_localizations.dart'; -import 'package:{{project_name.snakeCase()}}/core/extensions/app_localizations_x.dart';{{/enable_l10n}} -import 'package:{{project_name.snakeCase()}}/presentation/pages/initial/initial_page.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_screenutil/flutter_screenutil.dart'; - -class WidgetTree extends StatelessWidget { - const WidgetTree({super.key}); - - @override - Widget build(BuildContext context) { - {{#enable_router}} - final GoRouter _router = GoRouter( - initialLocation: '/', - routes: AppRouter.routes, - debugLogDiagnostics: true, - errorBuilder: (_, __) => Container( - color: Colors.red, - ), - ); - {{/enable_router}} - - return ScreenUtilInit( - designSize: const Size(455, 985), - builder: (context, child) { - {{#enable_router}} - return MaterialApp.router( - debugShowCheckedModeBanner: false, - title: '{{project_name.titleCase()}}', - routeInformationParser: _router.routeInformationParser, - routeInformationProvider: _router.routeInformationProvider, - routerDelegate: _router.routerDelegate, - theme: AppTheme.defaultTheme, - {{#enable_l10n}}localizationsDelegates: const [ - AppLocalizations.delegate, - GlobalMaterialLocalizations.delegate, - GlobalWidgetsLocalizations.delegate, - GlobalCupertinoLocalizations.delegate, - ], - supportedLocales: AppLocalizations.supportedLocales,{{/enable_l10n}} - ); - {{/enable_router}}{{^enable_router}} - return MaterialApp( - debugShowCheckedModeBanner: false, - title: '{{project_name.titleCase()}}', - theme: AppTheme.defaultTheme, - home: const InitialPage(), - {{#enable_l10n}}localizationsDelegates: const [ - AppLocalizations.delegate, - GlobalMaterialLocalizations.delegate, - GlobalWidgetsLocalizations.delegate, - GlobalCupertinoLocalizations.delegate, - ], - supportedLocales: AppLocalizations.supportedLocales,{{/enable_l10n}} - ); - {{/enable_router}} - }, - ); - } -} diff --git a/bricks/wyatt_clean_code/__brick__/pubspec.yaml b/bricks/wyatt_clean_code/__brick__/pubspec.yaml index d8add2c..529d443 100644 --- a/bricks/wyatt_clean_code/__brick__/pubspec.yaml +++ b/bricks/wyatt_clean_code/__brick__/pubspec.yaml @@ -1,79 +1,125 @@ name: {{#snakeCase}}{{project_name}}{{/snakeCase}} description: {{{description}}} -version: 1.0.0+1 -publish_to: none +# The following line prevents the package from being accidentally published to +# pub.dev using `flutter pub publish`. This is preferred for private packages. +publish_to: "none" + +# The following defines the version and build number for your application. +# A version number is three numbers separated by dots, like 1.2.43 +# followed by an optional build number separated by a +. +# Both the version and the builder number may be overridden in flutter +# build by specifying --build-name and --build-number, respectively. +# In Android, build-name is used as versionName while build-number used as versionCode. +# Read more about Android versioning at https://developer.android.com/studio/publish/versioning +# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. +# Read more about iOS versioning at +# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html +version: 1.0.0+1 environment: sdk: ">=2.17.0 <3.0.0" + flutter: ">=3.0.0" +# Dependencies specify other packages that your package needs in order to work. +# To automatically upgrade your package dependencies to the latest versions +# consider running `flutter pub upgrade --major-versions`. Alternatively, +# dependencies can be manually updated by changing the version numbers below to +# the latest version available on pub.dev. To see which dependencies have newer +# versions available, run `flutter pub outdated`. dependencies: flutter: sdk: flutter - #{{#enable_l10n}} Localization flutter_localizations: sdk: flutter intl: ^0.17.0 - #{{/enable_l10n}}{{#enable_auth}} Authentication - wyatt_authentication_bloc: - git: - url: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages - ref: wyatt_authentication_bloc-v0.2.1 - path: packages/wyatt_authentication_bloc - #{{/enable_auth}}{{#enable_forms}} Forms - wyatt_form_bloc: - git: - url: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages - ref: wyatt_form_bloc-v0.0.2 - path: packages/wyatt_form_bloc - #{{/enable_forms}}{{#enable_freezed}} Freezed: model generation - freezed_annotation: ^2.0.3 - json_annotation: ^4.5.0 - #{{/enable_freezed}}{{#enable_http}} Advanced HTTP Client - wyatt_http_client: - git: - url: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages - ref: wyatt_http_client-v1.2.0 - path: packages/wyatt_http_client - #{{/enable_http}}{{#enable_router}} Router - go_router: ^4.1.0 - #{{/enable_router}} - - flutter_bloc: ^8.0.1 + go_router: ^4.1.1 equatable: ^2.0.3 - flutter_screenutil: ^5.5.3+2 + freezed_annotation: ^2.1.0 + json_annotation: ^4.6.0 + cupertino_icons: ^1.0.5 + get_it: ^7.2.0 + logger: ^1.1.0 gap: ^2.0.0 - + flutter_bloc: ^8.0.1 wyatt_bloc_helper: git: url: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages - ref: wyatt_bloc_helper-v1.1.0 + ref: bloc/feature/fix_and_repo path: packages/wyatt_bloc_helper + wyatt_type_utils: + git: + url: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages + ref: wyatt_type_utils-v0.0.2 + path: packages/wyatt_type_utils + dev_dependencies: flutter_test: sdk: flutter - build_runner: ^2.1.11 - dependency_validator: ^3.2.0 + + dependency_validator: ^3.2.2 + + build_runner: ^2.2.0 flutter_gen_runner: ^4.3.0 - #{{#enable_freezed}} Freezed utils - freezed: ^2.0.3+1 - json_serializable: ^6.2.0 - #{{/enable_freezed}}{{#enable_analysis}} Analyzer + freezed: ^2.1.0+1 + json_serializable: ^6.3.1 + + # The "wyatt_analysis" package below contains a set of recommended lints to + # encourage good coding practices. The lint set provided by the package is + # activated in the `analysis_options.yaml` file located at the root of your + # package. See that file for information about deactivating specific lint + # rules and activating additional ones. wyatt_analysis: git: url: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages - ref: wyatt_analysis-v2.1.0 + ref: wyatt_analysis-v2.2.1 path: packages/wyatt_analysis - #{{/enable_analysis}}{{^enable_analysis}} - flutter_lints: ^1.0.0 - #{{/enable_analysis}} +# For information on the generic Dart part of this file, see the +# following page: https://dart.dev/tools/pub/pubspec + +# The following secion is specific to FlutterGen flutter_gen: colors: inputs: - - assets/colors/dark.xml + - assets/colors.xml +# The following section is specific to Flutter packages. flutter: + # The following line ensures that the Material Icons font is + # included with your application, so that you can use the icons in + # the material Icons class. uses-material-design: true - {{#enable_l10n}}generate: true{{/enable_l10n}} + + generate: true + + # To add assets to your application, add an assets section, like this: + assets: + - assets/images/ + + # An image asset can refer to one or more resolution-specific "variants", see + # https://flutter.dev/assets-and-images/#resolution-aware + + # For details regarding adding assets from package dependencies, see + # https://flutter.dev/assets-and-images/#from-packages + + # To add custom fonts to your application, add a fonts section here, + # in this "flutter" section. Each entry in this list should have a + # "family" key with the font family name, and a "fonts" key with a + # list giving the asset and other descriptors for the font. For + # example: + # fonts: + # - family: Schyler + # fonts: + # - asset: fonts/Schyler-Regular.ttf + # - asset: fonts/Schyler-Italic.ttf + # style: italic + # - family: Trajan Pro + # fonts: + # - asset: fonts/TrajanPro.ttf + # - asset: fonts/TrajanPro_Bold.ttf + # weight: 700 + # + # For details regarding fonts from package dependencies, + # see https://flutter.dev/custom-fonts/#from-packages diff --git a/bricks/wyatt_clean_code/__brick__/scripts/.gitkeep b/bricks/wyatt_clean_code/__brick__/scripts/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/bricks/wyatt_clean_code/__brick__/{{#enable_android}}android{{/enable_android}}/app/build.gradle b/bricks/wyatt_clean_code/__brick__/{{#enable_android}}android{{/enable_android}}/app/build.gradle index 7b36f80..42c94ef 100644 --- a/bricks/wyatt_clean_code/__brick__/{{#enable_android}}android{{/enable_android}}/app/build.gradle +++ b/bricks/wyatt_clean_code/__brick__/{{#enable_android}}android{{/enable_android}}/app/build.gradle @@ -21,6 +21,12 @@ if (flutterVersionName == null) { flutterVersionName = '1.0' } +def keystoreProperties = new Properties() +def keystorePropertiesFile = rootProject.file('key.properties') +if (keystorePropertiesFile.exists()) { + keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) +} + apply plugin: 'com.android.application' apply plugin: 'kotlin-android' apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" @@ -44,7 +50,7 @@ android { defaultConfig { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). - applicationId "{{#dotCase}}{{org_name}}{{/dotCase}}.{{#snakeCase}}{{project_name}}{{/snakeCase}}" + applicationId "com.example.{{#snakeCase}}{{project_name}}{{/snakeCase}}" // You can update the following values to match your application needs. // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration. minSdkVersion flutter.minSdkVersion @@ -53,10 +59,50 @@ android { versionName flutterVersionName } + signingConfigs { + if (System.getenv("ANDROID_KEYSTORE_PATH")) { + release { + storeFile file(System.getenv("ANDROID_KEYSTORE_PATH")) + keyAlias System.getenv("ANDROID_KEYSTORE_ALIAS") + keyPassword System.getenv("ANDROID_KEYSTORE_PRIVATE_KEY_PASSWORD") + storePassword System.getenv("ANDROID_KEYSTORE_PASSWORD") + } + } else { + release { + keyAlias keystoreProperties['keyAlias'] + keyPassword keystoreProperties['keyPassword'] + storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null + storePassword keystoreProperties['storePassword'] + } + } + } + + flavorDimensions "default" + productFlavors { + production { + dimension "default" + applicationIdSuffix "" + manifestPlaceholders = [appName: "{{#titleCase}}{{project_name}}{{/titleCase}}"] + } + staging { + dimension "default" + applicationIdSuffix ".stg" + manifestPlaceholders = [appName: "[STG] {{#titleCase}}{{project_name}}{{/titleCase}}"] + } + development { + dimension "default" + applicationIdSuffix ".dev" + manifestPlaceholders = [appName: "[DEV] {{#titleCase}}{{project_name}}{{/titleCase}}"] + } + } + buildTypes { release { - // TODO: Add your own signing config for the release build. - // Signing with the debug keys for now, so `flutter run --release` works. + signingConfig signingConfigs.release + minifyEnabled true + proguardFiles getDefaultProguardFile('proguard-android.txt') + } + debug { signingConfig signingConfigs.debug } } diff --git a/bricks/wyatt_clean_code/__brick__/{{#enable_android}}android{{/enable_android}}/app/src/debug/AndroidManifest.xml b/bricks/wyatt_clean_code/__brick__/{{#enable_android}}android{{/enable_android}}/app/src/debug/AndroidManifest.xml index dfa6d61..60d9d23 100644 --- a/bricks/wyatt_clean_code/__brick__/{{#enable_android}}android{{/enable_android}}/app/src/debug/AndroidManifest.xml +++ b/bricks/wyatt_clean_code/__brick__/{{#enable_android}}android{{/enable_android}}/app/src/debug/AndroidManifest.xml @@ -1,5 +1,5 @@ + package="com.example.{{#snakeCase}}{{project_name}}{{/snakeCase}}"> - + - {{project_name.titleCase()}} + {{#titleCase}}{{project_name}}{{/titleCase}}