├── .fvmrc ├── .github ├── CODEOWNERS ├── PULL_REQUEST_TEMPLATE.md ├── dependabot.yaml ├── labeler.yml ├── semantic.yml └── workflows │ ├── main.yaml │ ├── pr-labeler.yaml │ └── semantic-pr.yaml ├── .gitignore ├── .idea └── runConfigurations │ ├── development.xml │ ├── production.xml │ └── staging.xml ├── .metadata ├── .vscode ├── extensions.json └── launch.json ├── LICENSE ├── Makefile ├── README.md ├── analysis_options.yaml ├── android ├── .gitignore ├── app │ ├── build.gradle │ └── src │ │ ├── debug │ │ └── AndroidManifest.xml │ │ ├── development │ │ ├── ic_launcher-playstore.png │ │ └── res │ │ │ ├── drawable │ │ │ └── ic_launcher_foreground.xml │ │ │ ├── mipmap-anydpi-v26 │ │ │ ├── ic_launcher.xml │ │ │ └── ic_launcher_round.xml │ │ │ ├── mipmap-hdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-mdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxxhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ └── values │ │ │ └── ic_launcher_background.xml │ │ ├── main │ │ ├── AndroidManifest.xml │ │ ├── ic_launcher-playstore.png │ │ ├── kotlin │ │ │ └── dev │ │ │ │ └── adryanev │ │ │ │ └── template │ │ │ │ └── MainActivity.kt │ │ └── res │ │ │ ├── drawable-v21 │ │ │ └── launch_background.xml │ │ │ ├── drawable │ │ │ ├── ic_launch_image.xml │ │ │ ├── ic_launcher_foreground.xml │ │ │ └── launch_background.xml │ │ │ ├── mipmap-anydpi-v26 │ │ │ ├── ic_launcher.xml │ │ │ └── ic_launcher_round.xml │ │ │ ├── mipmap-hdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-mdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxxhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ │ ├── values-night │ │ │ └── styles.xml │ │ │ └── values │ │ │ ├── ic_launcher_background.xml │ │ │ └── styles.xml │ │ ├── profile │ │ └── AndroidManifest.xml │ │ └── staging │ │ ├── ic_launcher-playstore.png │ │ └── res │ │ ├── drawable │ │ └── ic_launcher_foreground.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ └── values │ │ └── ic_launcher_background.xml ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ └── gradle-wrapper.properties └── settings.gradle ├── assets ├── fonts │ └── .gitkeep ├── google_fonts │ ├── OFL.txt │ ├── Poppins-Black.ttf │ ├── Poppins-BlackItalic.ttf │ ├── Poppins-Bold.ttf │ ├── Poppins-BoldItalic.ttf │ ├── Poppins-ExtraBold.ttf │ ├── Poppins-ExtraBoldItalic.ttf │ ├── Poppins-ExtraLight.ttf │ ├── Poppins-ExtraLightItalic.ttf │ ├── Poppins-Italic.ttf │ ├── Poppins-Light.ttf │ ├── Poppins-LightItalic.ttf │ ├── Poppins-Medium.ttf │ ├── Poppins-MediumItalic.ttf │ ├── Poppins-Regular.ttf │ ├── Poppins-SemiBold.ttf │ ├── Poppins-SemiBoldItalic.ttf │ ├── Poppins-Thin.ttf │ └── Poppins-ThinItalic.ttf ├── icons │ └── .gitkeep └── images │ └── .gitkeep ├── build.yaml ├── coverage_badge.svg ├── flutter_native_splash.yaml ├── ios ├── .gitignore ├── Flutter │ ├── AppFrameworkInfo.plist │ ├── Debug.xcconfig │ └── Release.xcconfig ├── Podfile ├── Runner.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ └── WorkspaceSettings.xcsettings │ └── xcshareddata │ │ └── xcschemes │ │ ├── Runner.xcscheme │ │ ├── development.xcscheme │ │ ├── production.xcscheme │ │ └── staging.xcscheme ├── Runner.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ ├── IDEWorkspaceChecks.plist │ │ └── WorkspaceSettings.xcsettings ├── Runner │ ├── AppDelegate.swift │ ├── Assets.xcassets │ │ ├── AppIcon-dev.appiconset │ │ │ ├── 100.png │ │ │ ├── 1024.png │ │ │ ├── 114.png │ │ │ ├── 120.png │ │ │ ├── 128.png │ │ │ ├── 144.png │ │ │ ├── 152.png │ │ │ ├── 16.png │ │ │ ├── 167.png │ │ │ ├── 172.png │ │ │ ├── 180.png │ │ │ ├── 196.png │ │ │ ├── 20.png │ │ │ ├── 216.png │ │ │ ├── 256.png │ │ │ ├── 29.png │ │ │ ├── 32.png │ │ │ ├── 40.png │ │ │ ├── 48.png │ │ │ ├── 50.png │ │ │ ├── 512.png │ │ │ ├── 55.png │ │ │ ├── 57.png │ │ │ ├── 58.png │ │ │ ├── 60.png │ │ │ ├── 64.png │ │ │ ├── 72.png │ │ │ ├── 76.png │ │ │ ├── 80.png │ │ │ ├── 87.png │ │ │ ├── 88.png │ │ │ └── Contents.json │ │ ├── AppIcon-stg.appiconset │ │ │ ├── 100.png │ │ │ ├── 1024.png │ │ │ ├── 114.png │ │ │ ├── 120.png │ │ │ ├── 128.png │ │ │ ├── 144.png │ │ │ ├── 152.png │ │ │ ├── 16.png │ │ │ ├── 167.png │ │ │ ├── 172.png │ │ │ ├── 180.png │ │ │ ├── 196.png │ │ │ ├── 20.png │ │ │ ├── 216.png │ │ │ ├── 256.png │ │ │ ├── 29.png │ │ │ ├── 32.png │ │ │ ├── 40.png │ │ │ ├── 48.png │ │ │ ├── 50.png │ │ │ ├── 512.png │ │ │ ├── 55.png │ │ │ ├── 57.png │ │ │ ├── 58.png │ │ │ ├── 60.png │ │ │ ├── 64.png │ │ │ ├── 72.png │ │ │ ├── 76.png │ │ │ ├── 80.png │ │ │ ├── 87.png │ │ │ ├── 88.png │ │ │ └── Contents.json │ │ ├── AppIcon.appiconset │ │ │ ├── 100.png │ │ │ ├── 1024.png │ │ │ ├── 114.png │ │ │ ├── 120.png │ │ │ ├── 128.png │ │ │ ├── 144.png │ │ │ ├── 152.png │ │ │ ├── 16.png │ │ │ ├── 167.png │ │ │ ├── 172.png │ │ │ ├── 180.png │ │ │ ├── 196.png │ │ │ ├── 20.png │ │ │ ├── 216.png │ │ │ ├── 256.png │ │ │ ├── 29.png │ │ │ ├── 32.png │ │ │ ├── 40.png │ │ │ ├── 48.png │ │ │ ├── 50.png │ │ │ ├── 512.png │ │ │ ├── 55.png │ │ │ ├── 57.png │ │ │ ├── 58.png │ │ │ ├── 60.png │ │ │ ├── 64.png │ │ │ ├── 72.png │ │ │ ├── 76.png │ │ │ ├── 80.png │ │ │ ├── 87.png │ │ │ ├── 88.png │ │ │ └── Contents.json │ │ ├── Contents.json │ │ └── LaunchImage.imageset │ │ │ ├── Contents.json │ │ │ ├── LaunchImage@1x.png │ │ │ ├── LaunchImage@2x.png │ │ │ ├── LaunchImage@3x.png │ │ │ └── README.md │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ ├── Info.plist │ └── Runner-Bridging-Header.h └── RunnerTests │ └── RunnerTests.swift ├── l10n.yaml ├── lib ├── app │ ├── app.dart │ ├── router │ │ └── app_router.dart │ └── view │ │ └── app.dart ├── bootstrap.dart ├── core │ ├── di │ │ ├── app_module.dart │ │ └── storage_module.dart │ ├── domain │ │ ├── entities │ │ │ ├── value_object.dart │ │ │ └── value_validators.dart │ │ ├── failures │ │ │ ├── errors.dart │ │ │ ├── failure.dart │ │ │ └── value_failure.dart │ │ └── usecases │ │ │ └── use_case.dart │ ├── extensions │ │ ├── context_extensions.dart │ │ └── dartz_extensions.dart │ ├── presentation │ │ └── mixins │ │ │ └── failure_message_handler.dart │ ├── storages │ │ └── local_storages.dart │ └── utils │ │ ├── colors.dart │ │ ├── constants.dart │ │ └── dimensions.dart ├── features │ └── counter │ │ ├── counter.dart │ │ ├── data │ │ ├── datasources │ │ │ └── .gitkeep │ │ ├── models │ │ │ └── .gitkeep │ │ └── repositories │ │ │ └── .gitkeep │ │ ├── domain │ │ ├── entities │ │ │ └── .gitkeep │ │ ├── repositories │ │ │ └── .gitkeep │ │ └── usecases │ │ │ └── .gitkeep │ │ └── presentation │ │ ├── blocs │ │ └── counter_cubit.dart │ │ ├── pages │ │ └── counter_page.dart │ │ └── widgets │ │ └── .gitkeep ├── injector.dart ├── l10n │ ├── arb │ │ ├── app_en.arb │ │ └── app_id.arb │ └── l10n.dart ├── main_development.dart ├── main_production.dart ├── main_staging.dart └── shared │ ├── domain │ ├── entities │ │ └── value_objects.dart │ └── formz │ │ ├── email_input.dart │ │ ├── password_confirmation_input.dart │ │ └── password_input.dart │ └── flash │ └── presentation │ └── blocs │ └── cubit │ ├── flash_cubit.dart │ └── flash_state.dart ├── pubspec.lock ├── pubspec.yaml └── test ├── app └── view │ └── app_test.dart ├── core ├── domain │ ├── entities │ │ ├── value_object_test.dart │ │ └── value_validators_test.dart │ ├── failures │ │ ├── errors_test.dart │ │ ├── failure.codegen_test.dart │ │ └── value_failure.codegen_test.dart │ └── usecases │ │ └── use_case_test.dart └── extensions │ ├── context_extensions_test.dart │ └── dartz_extensions_test.dart ├── features └── counter │ ├── data │ ├── datasources │ │ └── .gitkeep │ ├── models │ │ └── .gitkeep │ └── repositories │ │ └── .gitkeep │ ├── domain │ ├── entities │ │ └── .gitkeep │ ├── repositories │ │ └── .gitkeep │ └── usecases │ │ └── .gitkeep │ └── presentation │ ├── blocs │ └── counter_cubit_test.dart │ ├── pages │ └── counter_page_test.dart │ └── widgets │ └── .gitkeep ├── fixtures ├── fixture_reader.dart └── user │ └── user.json ├── helpers ├── configure_injector.dart ├── helpers.dart └── pump_app.dart └── shared └── domain ├── entities └── value_objects_test.dart └── formz ├── email_input_test.dart ├── password_confirmation_input_test.dart └── password_input_test.dart /.fvmrc: -------------------------------------------------------------------------------- 1 | { 2 | "flutter": "stable" 3 | } -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # Every request must be reviewed and accepted by 2 | 3 | * @adryanev 4 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Description 2 | 3 | What: 4 | 5 | 1. What changes did you make? 6 | 7 | How: 8 | 9 | 1. How do you change it? 10 | 2. If it is a breaking change, code refactor. Explain how others should migrate to the new API. 11 | 12 | Why: 13 | 14 | 1. What is the reason for the change? 15 | 2. If it is a breaking change, code refactor. What justifies the change? 16 | 17 | 18 | --- 19 | 20 | ## Type of Change 21 | 22 | - [ ] ✨ New feature (non-breaking change which adds functionality) 23 | - [ ] 🛠️ Bug fix (non-breaking change which fixes an issue) 24 | - [ ] ❌ Breaking change (fix or feature that would cause existing functionality to change) 25 | - [ ] 🧹 Code refactor 26 | - [ ] ✅ Build configuration change 27 | - [ ] 📝 Documentation 28 | - [ ] 🗑️ Chore 29 | 30 | ## Code Checklist 31 | 32 | - [ ] Tested [test_documentation_video_link_here] or a screenshot. 33 | -------------------------------------------------------------------------------- /.github/dependabot.yaml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "github-actions" 4 | directory: "/" 5 | schedule: 6 | interval: "daily" 7 | - package-ecosystem: "pub" 8 | directory: "/" 9 | schedule: 10 | interval: "daily" 11 | -------------------------------------------------------------------------------- /.github/labeler.yml: -------------------------------------------------------------------------------- 1 | ci/cd: 2 | - any-glob-to-any-file: .github/workflows/* 3 | 4 | core: 5 | - any-glob-to-any-file: lib/core/** 6 | 7 | assets: 8 | - any-glob-to-any-file: assets/** 9 | 10 | domain: 11 | - any-glob-to-any-file: lib/features/**/domain/** 12 | 13 | data: 14 | - any-glob-to-any-file: lib/features/**/data/** 15 | 16 | presentation: 17 | - any-glob-to-any-file: lib/features/**/presentation/** 18 | 19 | feature: 20 | - any-glob-to-any-file: lib/features/** 21 | 22 | shared: 23 | - any-glob-to-any-file: lib/shared/** 24 | 25 | test: 26 | - any-glob-to-any-file: test/** 27 | 28 | documentation: 29 | - any-glob-to-any-file: [README.md, ./*.md] 30 | 31 | l10n: 32 | - any-glob-to-any-file: l10n/** 33 | 34 | router: 35 | - any-glob-to-any-file: lib/app/router/** 36 | 37 | -------------------------------------------------------------------------------- /.github/semantic.yml: -------------------------------------------------------------------------------- 1 | # Always validate the PR title, and ignore the commits 2 | titleOnly: true 3 | # By default types specified in commitizen/conventional-commit-types is used. 4 | # See: https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json 5 | # You can override the valid types 6 | types: 7 | - feat 8 | - fix 9 | - docs 10 | - style 11 | - refactor 12 | - perf 13 | - test 14 | - build 15 | - ci 16 | - chore 17 | - revert 18 | -------------------------------------------------------------------------------- /.github/workflows/main.yaml: -------------------------------------------------------------------------------- 1 | name: template 2 | 3 | concurrency: 4 | group: $-$ 5 | cancel-in-progress: true 6 | 7 | on: 8 | push: 9 | branches: 10 | - main 11 | - master 12 | pull_request: 13 | branches: 14 | - main 15 | - master 16 | 17 | jobs: 18 | build: 19 | uses: VeryGoodOpenSource/very_good_workflows/.github/workflows/flutter_package.yml@v1 20 | with: 21 | flutter_channel: stable 22 | min_coverage: 0 23 | setup: "flutter pub global activate very_good_cli && export PATH=$PATH:$HOME/.pub-cache/bin && dart run build_runner build --delete-conflicting-outputs" 24 | -------------------------------------------------------------------------------- /.github/workflows/pr-labeler.yaml: -------------------------------------------------------------------------------- 1 | name: Pull Request Labeling 2 | 3 | on: 4 | - pull_request 5 | 6 | jobs: 7 | triage: 8 | permissions: write-all 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/labeler@v5 12 | with: 13 | repo-token: "${{ secrets.GITHUB_TOKEN }}" 14 | -------------------------------------------------------------------------------- /.github/workflows/semantic-pr.yaml: -------------------------------------------------------------------------------- 1 | name: Lint PR 2 | 3 | on: 4 | pull_request_target: 5 | types: 6 | - opened 7 | - edited 8 | - synchronize 9 | 10 | jobs: 11 | main: 12 | permissions: write-all 13 | name: Validate PR title 14 | runs-on: ubuntu-latest 15 | steps: 16 | - uses: amannn/action-semantic-pull-request@v5 17 | id: lint_pr_title 18 | env: 19 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 20 | 21 | - uses: marocchino/sticky-pull-request-comment@v2 22 | # When the previous steps fails, the workflow would stop. By adding this 23 | # condition you can continue the execution with the populated error message. 24 | if: always() && (steps.lint_pr_title.outputs.error_message != null) 25 | with: 26 | header: pr-title-lint-error 27 | message: | 28 | Hey there and thank you for opening this pull request! 👋🏼 29 | 30 | We require pull request titles to follow the [Conventional Commits specification](https://www.conventionalcommits.org/en/v1.0.0/) and it looks like your proposed title needs to be adjusted. 31 | 32 | Details: 33 | 34 | ``` 35 | ${{ steps.lint_pr_title.outputs.error_message }} 36 | ``` 37 | 38 | # Delete a previous comment when the issue has been resolved 39 | - if: ${{ steps.lint_pr_title.outputs.error_message == null }} 40 | uses: marocchino/sticky-pull-request-comment@v2 41 | with: 42 | header: pr-title-lint-error 43 | delete: true 44 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.lock 4 | *.log 5 | *.pyc 6 | *.swp 7 | .DS_Store 8 | .atom/ 9 | .buildlog/ 10 | .history 11 | .svn/ 12 | 13 | # IntelliJ related 14 | *.iml 15 | *.ipr 16 | *.iws 17 | .idea/* 18 | 19 | # Visual Studio Code related 20 | .classpath 21 | .project 22 | .settings/ 23 | .vscode/* 24 | 25 | # Flutter repo-specific 26 | /bin/cache/ 27 | /bin/mingit/ 28 | /dev/benchmarks/mega_gallery/ 29 | /dev/bots/.recipe_deps 30 | /dev/bots/android_tools/ 31 | /dev/docs/doc/ 32 | /dev/docs/flutter.docs.zip 33 | /dev/docs/lib/ 34 | /dev/docs/pubspec.yaml 35 | /dev/integration_tests/**/xcuserdata 36 | /dev/integration_tests/**/Pods 37 | /packages/flutter/coverage/ 38 | version 39 | 40 | # packages file containing multi-root paths 41 | .packages.generated 42 | 43 | # Flutter/Dart/Pub related 44 | **/doc/api/ 45 | **/ios/Flutter/.last_build_id 46 | .dart_tool/ 47 | .flutter-plugins 48 | .flutter-plugins-dependencies 49 | .packages 50 | .pub-cache/ 51 | .pub/ 52 | build/ 53 | flutter_*.png 54 | linked_*.ds 55 | unlinked.ds 56 | unlinked_spec.ds 57 | .fvm/ 58 | 59 | # Android related 60 | **/android/**/gradle-wrapper.jar 61 | **/android/.gradle 62 | **/android/captures/ 63 | **/android/gradlew 64 | **/android/gradlew.bat 65 | **/android/local.properties 66 | **/android/**/GeneratedPluginRegistrant.java 67 | **/android/key.properties 68 | **/android/.idea/ 69 | **/android/app/debug 70 | **/android/app/profile 71 | **/android/app/release 72 | *.jks 73 | 74 | # iOS/XCode related 75 | **/ios/**/*.mode1v3 76 | **/ios/**/*.mode2v3 77 | **/ios/**/*.moved-aside 78 | **/ios/**/*.pbxuser 79 | **/ios/**/*.perspectivev3 80 | **/ios/**/*sync/ 81 | **/ios/**/.sconsign.dblite 82 | **/ios/**/.tags* 83 | **/ios/**/.vagrant/ 84 | **/ios/**/DerivedData/ 85 | **/ios/**/Icon? 86 | **/ios/**/Pods/ 87 | **/ios/**/.symlinks/ 88 | **/ios/**/profile 89 | **/ios/**/xcuserdata 90 | **/ios/.generated/ 91 | **/ios/Flutter/App.framework 92 | **/ios/Flutter/Flutter.framework 93 | **/ios/Flutter/Flutter.podspec 94 | **/ios/Flutter/Generated.xcconfig 95 | **/ios/Flutter/app.flx 96 | **/ios/Flutter/app.zip 97 | **/ios/Flutter/.last_build_id 98 | **/ios/Flutter/flutter_assets/ 99 | **/ios/Flutter/flutter_export_environment.sh 100 | **/ios/ServiceDefinitions.json 101 | **/ios/Runner/GeneratedPluginRegistrant.* 102 | 103 | # Windows Related 104 | **/windows/flutter/generated_plugin_registrant.cc 105 | **/windows/flutter/generated_plugin_registrant.h 106 | **/windows/flutter/generated_plugins.cmake 107 | 108 | # Linux Related 109 | **/linux/flutter/generated_plugin_registrant.cc 110 | **/linux/flutter/generated_plugin_registrant.h 111 | **/linux/flutter/generated_plugins.cmake 112 | 113 | # Coverage 114 | coverage/ 115 | 116 | # Submodules 117 | !pubspec.lock 118 | packages/**/pubspec.lock 119 | 120 | # Web related 121 | lib/generated_plugin_registrant.dart 122 | 123 | # Symbolication related 124 | app.*.symbols 125 | 126 | # Obfuscation related 127 | app.*.map.json 128 | 129 | # Generated build runner file 130 | **.config.dart 131 | **.freezed.dart 132 | **.g.dart 133 | **.gen.dart 134 | 135 | # Exceptions to the above rules. 136 | !**/ios/**/default.mode1v3 137 | !**/ios/**/default.mode2v3 138 | !**/ios/**/default.pbxuser 139 | !**/ios/**/default.perspectivev3 140 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages 141 | !/dev/ci/**/Gemfile.lock 142 | !.vscode/extensions.json 143 | !.vscode/launch.json 144 | !.idea/codeStyles/ 145 | !.idea/dictionaries/ 146 | !.idea/runConfigurations/ 147 | -------------------------------------------------------------------------------- /.idea/runConfigurations/development.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | -------------------------------------------------------------------------------- /.idea/runConfigurations/production.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | -------------------------------------------------------------------------------- /.idea/runConfigurations/staging.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | -------------------------------------------------------------------------------- /.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: 9b2d32b605630f28625709ebd9d78ab3016b2bf6 8 | channel: stable 9 | 10 | project_type: app 11 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=827846 3 | // for the documentation about the extensions.json format 4 | "recommendations": [ 5 | "dart-code.dart-code", 6 | "dart-code.flutter", 7 | "felixangelov.bloc" 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "Launch development", 9 | "request": "launch", 10 | "type": "dart", 11 | "program": "lib/main_development.dart", 12 | "args": [ 13 | "--flavor", 14 | "development", 15 | "--target", 16 | "lib/main_development.dart" 17 | ] 18 | }, 19 | { 20 | "name": "Launch staging", 21 | "request": "launch", 22 | "type": "dart", 23 | "program": "lib/main_staging.dart", 24 | "args": ["--flavor", "staging", "--target", "lib/main_staging.dart"] 25 | }, 26 | { 27 | "name": "Launch production", 28 | "request": "launch", 29 | "type": "dart", 30 | "program": "lib/main_production.dart", 31 | "args": ["--flavor", "production", "--target", "lib/main_production.dart"] 32 | } 33 | ] 34 | } 35 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Very Good Ventures 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: get 2 | get: 3 | @flutter pub get 4 | 5 | .PHONY: build 6 | build: 7 | @dart pub run build_runner build --delete-conflicting-outputs 8 | 9 | .PHONY: watch 10 | watch: 11 | @dart pub run build_runner watch --delete-conflicting-outputs 12 | 13 | .PHONY: apk-dev 14 | apk-dev: 15 | @flutter build apk --debug --flavor development --target lib/main_development.dart 16 | 17 | .PHONY: apk-stg 18 | apk-stg: 19 | @flutter build apk --profile --flavor staging --target lib/main_staging.dart 20 | 21 | .PHONY: apk-prod 22 | apk-prod: 23 | @flutter build apk --release --flavor production --target lib/main_production.dart 24 | 25 | .PHONY: ipa-dev 26 | ipa-dev: 27 | @flutter build ipa --debug --flavor development --target lib/main_development.dart 28 | 29 | .PHONY: ipa-stg 30 | ipa-stg: 31 | @flutter build ipa --profile --flavor staging --target lib/main_staging.dart 32 | 33 | .PHONY: ipa-prod 34 | ipa-prod: 35 | @flutter build ipa --release --flavor production --target lib/main_production.dart 36 | 37 | .PHONY: test 38 | test: 39 | @flutter test --coverage --test-randomize-ordering-seed random 40 | 41 | .PHONY: fix 42 | fix: 43 | @dart fix --apply 44 | 45 | .PHONY: check-fix 46 | check-fix: 47 | @dart fix --dry-run 48 | 49 | .PHONY: firebase-dev 50 | firebase-dev: 51 | @flutterfire config -y --account ${FIREBASE_EMAIL} --project=${FIREBASE_PROJECT_ID_DEV} --out=lib/firebase_options_dev.dart --ios-bundle-id=${PROJECT_PACKAGE}.dev --android-package-name=${PROJECT_PACKAGE}.dev 52 | 53 | .PHONY: firebase-stg 54 | firebase-stg: 55 | @flutterfire config -y --account ${FIREBASE_EMAIL} --project=${FIREBASE_PROJECT_ID_STG} --out=lib/firebase_options_stg.dart --ios-bundle-id=${PROJECT_PACKAGE}.stg --android-package-name=${PROJECT_PACKAGE}.stg 56 | 57 | .PHONY: firebase-prod 58 | firebase-prod: 59 | @flutterfire config -y --account ${FIREBASE_EMAIL} --project=${FIREBASE_PROJECT_ID_PROD} --out=lib/firebase_options.dart --ios-bundle-id=${PROJECT_PACKAGE} --android-package-name=${PROJECT_PACKAGE} 60 | 61 | .PHONY: analyze 62 | analyze: 63 | @dart analyze lib test 64 | 65 | .PHONY: format 66 | format: 67 | @dart format --set-exit-if-changed lib test 68 | 69 | .PHONY: prepare 70 | prepare: fix format analyze -------------------------------------------------------------------------------- /analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:very_good_analysis/analysis_options.5.1.0.yaml 2 | linter: 3 | rules: 4 | public_member_api_docs: false 5 | analyzer: 6 | exclude: 7 | - "**/*.g.dart" 8 | - "**/*.freezed.dart" 9 | - "**/*.gen.dart" 10 | - "**/*.config.dart" 11 | - lib/firebase_options.dart 12 | - lib/firebase_options_dev.dart 13 | - lib/firebase_options_stg.dart 14 | errors: 15 | invalid_annotation_target: ignore 16 | one_member_abstracts: ignore 17 | -------------------------------------------------------------------------------- /android/.gitignore: -------------------------------------------------------------------------------- 1 | gradle-wrapper.jar 2 | /.gradle 3 | /captures/ 4 | /local.properties 5 | GeneratedPluginRegistrant.java 6 | 7 | # Remember to never publicly share your keystore. 8 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app 9 | key.properties 10 | **/*.keystore 11 | **/*.jks 12 | -------------------------------------------------------------------------------- /android/app/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id "com.android.application" 3 | id "kotlin-android" 4 | id "dev.flutter.flutter-gradle-plugin" 5 | } 6 | 7 | def localProperties = new Properties() 8 | def localPropertiesFile = rootProject.file('local.properties') 9 | if (localPropertiesFile.exists()) { 10 | localPropertiesFile.withReader('UTF-8') { reader -> 11 | localProperties.load(reader) 12 | } 13 | } 14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 15 | if (flutterVersionCode == null) { 16 | flutterVersionCode = '1' 17 | } 18 | 19 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 20 | if (flutterVersionName == null) { 21 | flutterVersionName = '1.0' 22 | } 23 | 24 | def keystoreProperties = new Properties() 25 | def keystorePropertiesFile = rootProject.file('key.properties') 26 | if (keystorePropertiesFile.exists()) { 27 | keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) 28 | } 29 | 30 | android { 31 | namespace "dev.adryanev.template" 32 | compileSdkVersion flutter.compileSdkVersion 33 | ndkVersion flutter.ndkVersion 34 | 35 | compileOptions { 36 | sourceCompatibility JavaVersion.VERSION_17 37 | targetCompatibility JavaVersion.VERSION_17 38 | } 39 | 40 | kotlinOptions { 41 | jvmTarget = JavaVersion.VERSION_17 42 | } 43 | 44 | sourceSets { 45 | main.java.srcDirs += 'src/main/kotlin' 46 | } 47 | 48 | defaultConfig { 49 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 50 | applicationId "dev.adryanev.template" 51 | minSdkVersion flutter.minSdkVersion 52 | targetSdkVersion flutter.targetSdkVersion 53 | versionCode flutterVersionCode.toInteger() 54 | versionName flutterVersionName 55 | } 56 | 57 | signingConfigs { 58 | if (System.getenv("ANDROID_KEYSTORE_PATH")) { 59 | release { 60 | storeFile file(System.getenv("ANDROID_KEYSTORE_PATH")) 61 | keyAlias System.getenv("ANDROID_KEYSTORE_ALIAS") 62 | keyPassword System.getenv("ANDROID_KEYSTORE_PRIVATE_KEY_PASSWORD") 63 | storePassword System.getenv("ANDROID_KEYSTORE_PASSWORD") 64 | } 65 | } else { 66 | release { 67 | keyAlias keystoreProperties['keyAlias'] 68 | keyPassword keystoreProperties['keyPassword'] 69 | storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null 70 | storePassword keystoreProperties['storePassword'] 71 | } 72 | } 73 | } 74 | 75 | flavorDimensions "default" 76 | productFlavors { 77 | production { 78 | dimension "default" 79 | applicationIdSuffix "" 80 | manifestPlaceholders = [appName: "Template"] 81 | } 82 | staging { 83 | dimension "default" 84 | applicationIdSuffix ".stg" 85 | manifestPlaceholders = [appName: "[STG] Template"] 86 | } 87 | development { 88 | dimension "default" 89 | applicationIdSuffix ".dev" 90 | manifestPlaceholders = [appName: "[DEV] Template"] 91 | } 92 | } 93 | 94 | buildTypes { 95 | release { 96 | signingConfig signingConfigs.release 97 | minifyEnabled true 98 | proguardFiles getDefaultProguardFile('proguard-android.txt') 99 | } 100 | debug { 101 | signingConfig signingConfigs.debug 102 | } 103 | } 104 | } 105 | 106 | flutter { 107 | source '../..' 108 | } 109 | 110 | dependencies { 111 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.9.20" 112 | def multidex_version = "2.0.1" 113 | implementation "androidx.multidex:multidex:$multidex_version" 114 | } 115 | -------------------------------------------------------------------------------- /android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /android/app/src/development/ic_launcher-playstore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/android/app/src/development/ic_launcher-playstore.png -------------------------------------------------------------------------------- /android/app/src/development/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /android/app/src/development/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /android/app/src/development/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/android/app/src/development/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/development/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/android/app/src/development/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android/app/src/development/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/android/app/src/development/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/development/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/android/app/src/development/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android/app/src/development/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/android/app/src/development/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/development/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/android/app/src/development/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android/app/src/development/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/android/app/src/development/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/development/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/android/app/src/development/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android/app/src/development/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/android/app/src/development/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/development/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/android/app/src/development/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android/app/src/development/res/values/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FFFFFF 4 | -------------------------------------------------------------------------------- /android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 14 | 18 | 22 | 23 | 24 | 25 | 26 | 27 | 29 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /android/app/src/main/ic_launcher-playstore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/android/app/src/main/ic_launcher-playstore.png -------------------------------------------------------------------------------- /android/app/src/main/kotlin/dev/adryanev/template/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package dev.adryanev.template 2 | 3 | import io.flutter.embedding.android.FlutterActivity 4 | 5 | class MainActivity: FlutterActivity() { 6 | } 7 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-v21/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable/ic_launch_image.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 12 | 13 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android/app/src/main/res/values-night/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /android/app/src/main/res/values/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FFFFFF 4 | -------------------------------------------------------------------------------- /android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /android/app/src/staging/ic_launcher-playstore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/android/app/src/staging/ic_launcher-playstore.png -------------------------------------------------------------------------------- /android/app/src/staging/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /android/app/src/staging/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /android/app/src/staging/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/android/app/src/staging/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/staging/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/android/app/src/staging/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android/app/src/staging/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/android/app/src/staging/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/staging/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/android/app/src/staging/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android/app/src/staging/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/android/app/src/staging/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/staging/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/android/app/src/staging/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android/app/src/staging/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/android/app/src/staging/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/staging/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/android/app/src/staging/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android/app/src/staging/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/android/app/src/staging/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/staging/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/android/app/src/staging/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android/app/src/staging/res/values/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FFFFFF 4 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | allprojects { 2 | repositories { 3 | google() 4 | mavenCentral() 5 | } 6 | } 7 | 8 | rootProject.buildDir = '../build' 9 | subprojects { 10 | project.buildDir = "${rootProject.buildDir}/${project.name}" 11 | project.evaluationDependsOn(':app') 12 | } 13 | 14 | tasks.register("clean", Delete) { 15 | delete rootProject.buildDir 16 | } 17 | -------------------------------------------------------------------------------- /android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | android.useAndroidX=true 3 | android.enableJetifier=true 4 | -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri Jun 23 08:50:38 CEST 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-all.zip -------------------------------------------------------------------------------- /android/settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | def flutterSdkPath = { 3 | def properties = new Properties() 4 | file("local.properties").withInputStream { properties.load(it) } 5 | def flutterSdkPath = properties.getProperty("flutter.sdk") 6 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties" 7 | return flutterSdkPath 8 | }() 9 | 10 | includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") 11 | 12 | repositories { 13 | google() 14 | mavenCentral() 15 | gradlePluginPortal() 16 | } 17 | } 18 | 19 | plugins { 20 | id "dev.flutter.flutter-plugin-loader" version "1.0.0" 21 | id "com.android.application" version "8.2.1" apply false 22 | id "org.jetbrains.kotlin.android" version "1.9.20" apply false 23 | } 24 | 25 | include ":app" -------------------------------------------------------------------------------- /assets/fonts/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/assets/fonts/.gitkeep -------------------------------------------------------------------------------- /assets/google_fonts/OFL.txt: -------------------------------------------------------------------------------- 1 | Copyright 2020 The Poppins Project Authors (https://github.com/itfoundry/Poppins) 2 | 3 | This Font Software is licensed under the SIL Open Font License, Version 1.1. 4 | This license is copied below, and is also available with a FAQ at: 5 | http://scripts.sil.org/OFL 6 | 7 | 8 | ----------------------------------------------------------- 9 | SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 10 | ----------------------------------------------------------- 11 | 12 | PREAMBLE 13 | The goals of the Open Font License (OFL) are to stimulate worldwide 14 | development of collaborative font projects, to support the font creation 15 | efforts of academic and linguistic communities, and to provide a free and 16 | open framework in which fonts may be shared and improved in partnership 17 | with others. 18 | 19 | The OFL allows the licensed fonts to be used, studied, modified and 20 | redistributed freely as long as they are not sold by themselves. The 21 | fonts, including any derivative works, can be bundled, embedded, 22 | redistributed and/or sold with any software provided that any reserved 23 | names are not used by derivative works. The fonts and derivatives, 24 | however, cannot be released under any other type of license. The 25 | requirement for fonts to remain under this license does not apply 26 | to any document created using the fonts or their derivatives. 27 | 28 | DEFINITIONS 29 | "Font Software" refers to the set of files released by the Copyright 30 | Holder(s) under this license and clearly marked as such. This may 31 | include source files, build scripts and documentation. 32 | 33 | "Reserved Font Name" refers to any names specified as such after the 34 | copyright statement(s). 35 | 36 | "Original Version" refers to the collection of Font Software components as 37 | distributed by the Copyright Holder(s). 38 | 39 | "Modified Version" refers to any derivative made by adding to, deleting, 40 | or substituting -- in part or in whole -- any of the components of the 41 | Original Version, by changing formats or by porting the Font Software to a 42 | new environment. 43 | 44 | "Author" refers to any designer, engineer, programmer, technical 45 | writer or other person who contributed to the Font Software. 46 | 47 | PERMISSION & CONDITIONS 48 | Permission is hereby granted, free of charge, to any person obtaining 49 | a copy of the Font Software, to use, study, copy, merge, embed, modify, 50 | redistribute, and sell modified and unmodified copies of the Font 51 | Software, subject to the following conditions: 52 | 53 | 1) Neither the Font Software nor any of its individual components, 54 | in Original or Modified Versions, may be sold by itself. 55 | 56 | 2) Original or Modified Versions of the Font Software may be bundled, 57 | redistributed and/or sold with any software, provided that each copy 58 | contains the above copyright notice and this license. These can be 59 | included either as stand-alone text files, human-readable headers or 60 | in the appropriate machine-readable metadata fields within text or 61 | binary files as long as those fields can be easily viewed by the user. 62 | 63 | 3) No Modified Version of the Font Software may use the Reserved Font 64 | Name(s) unless explicit written permission is granted by the corresponding 65 | Copyright Holder. This restriction only applies to the primary font name as 66 | presented to the users. 67 | 68 | 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font 69 | Software shall not be used to promote, endorse or advertise any 70 | Modified Version, except to acknowledge the contribution(s) of the 71 | Copyright Holder(s) and the Author(s) or with their explicit written 72 | permission. 73 | 74 | 5) The Font Software, modified or unmodified, in part or in whole, 75 | must be distributed entirely under this license, and must not be 76 | distributed under any other license. The requirement for fonts to 77 | remain under this license does not apply to any document created 78 | using the Font Software. 79 | 80 | TERMINATION 81 | This license becomes null and void if any of the above conditions are 82 | not met. 83 | 84 | DISCLAIMER 85 | THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 86 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF 87 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT 88 | OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE 89 | COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 90 | INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL 91 | DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 92 | FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM 93 | OTHER DEALINGS IN THE FONT SOFTWARE. 94 | -------------------------------------------------------------------------------- /assets/google_fonts/Poppins-Black.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/assets/google_fonts/Poppins-Black.ttf -------------------------------------------------------------------------------- /assets/google_fonts/Poppins-BlackItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/assets/google_fonts/Poppins-BlackItalic.ttf -------------------------------------------------------------------------------- /assets/google_fonts/Poppins-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/assets/google_fonts/Poppins-Bold.ttf -------------------------------------------------------------------------------- /assets/google_fonts/Poppins-BoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/assets/google_fonts/Poppins-BoldItalic.ttf -------------------------------------------------------------------------------- /assets/google_fonts/Poppins-ExtraBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/assets/google_fonts/Poppins-ExtraBold.ttf -------------------------------------------------------------------------------- /assets/google_fonts/Poppins-ExtraBoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/assets/google_fonts/Poppins-ExtraBoldItalic.ttf -------------------------------------------------------------------------------- /assets/google_fonts/Poppins-ExtraLight.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/assets/google_fonts/Poppins-ExtraLight.ttf -------------------------------------------------------------------------------- /assets/google_fonts/Poppins-ExtraLightItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/assets/google_fonts/Poppins-ExtraLightItalic.ttf -------------------------------------------------------------------------------- /assets/google_fonts/Poppins-Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/assets/google_fonts/Poppins-Italic.ttf -------------------------------------------------------------------------------- /assets/google_fonts/Poppins-Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/assets/google_fonts/Poppins-Light.ttf -------------------------------------------------------------------------------- /assets/google_fonts/Poppins-LightItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/assets/google_fonts/Poppins-LightItalic.ttf -------------------------------------------------------------------------------- /assets/google_fonts/Poppins-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/assets/google_fonts/Poppins-Medium.ttf -------------------------------------------------------------------------------- /assets/google_fonts/Poppins-MediumItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/assets/google_fonts/Poppins-MediumItalic.ttf -------------------------------------------------------------------------------- /assets/google_fonts/Poppins-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/assets/google_fonts/Poppins-Regular.ttf -------------------------------------------------------------------------------- /assets/google_fonts/Poppins-SemiBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/assets/google_fonts/Poppins-SemiBold.ttf -------------------------------------------------------------------------------- /assets/google_fonts/Poppins-SemiBoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/assets/google_fonts/Poppins-SemiBoldItalic.ttf -------------------------------------------------------------------------------- /assets/google_fonts/Poppins-Thin.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/assets/google_fonts/Poppins-Thin.ttf -------------------------------------------------------------------------------- /assets/google_fonts/Poppins-ThinItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/assets/google_fonts/Poppins-ThinItalic.ttf -------------------------------------------------------------------------------- /assets/icons/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/assets/icons/.gitkeep -------------------------------------------------------------------------------- /assets/images/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/assets/images/.gitkeep -------------------------------------------------------------------------------- /build.yaml: -------------------------------------------------------------------------------- 1 | targets: 2 | $default: 3 | builders: 4 | source_gen|combining_builder: 5 | options: 6 | ignore_for_file: 7 | - implicit_dynamic_parameter 8 | injectable_generator:injectable_config_builder: 9 | generate_for: 10 | - lib/injector.dart 11 | # mockito|mockBuilder: 12 | # generate_for: 13 | # - test/**.dart 14 | -------------------------------------------------------------------------------- /coverage_badge.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | coverage 16 | coverage 17 | 100% 18 | 100% 19 | 20 | -------------------------------------------------------------------------------- /flutter_native_splash.yaml: -------------------------------------------------------------------------------- 1 | flutter_native_splash: 2 | # This package generates native code to customize Flutter's default white native splash screen 3 | # with background color and splash image. 4 | # Customize the parameters below, and run the following command in the terminal: 5 | # flutter pub run flutter_native_splash:create 6 | # To restore Flutter's default white splash screen, run the following command in the terminal: 7 | # flutter pub run flutter_native_splash:remove 8 | 9 | # color or background_image is the only required parameter. Use color to set the background 10 | # of your splash screen to a solid color. Use background_image to set the background of your 11 | # splash screen to a png image. This is useful for gradients. The image will be stretch to the 12 | # size of the app. Only one parameter can be used, color and background_image cannot both be set. 13 | color: "#42a5f5" 14 | #background_image: "assets/background.png" 15 | 16 | # Optional parameters are listed below. To enable a parameter, uncomment the line by removing 17 | # the leading # character. 18 | 19 | # The image parameter allows you to specify an image used in the splash screen. It must be a 20 | # png file and should be sized for 4x pixel density. 21 | #image: assets/splash.png 22 | 23 | # The branding property allows you to specify an image used as branding in the splash screen. 24 | # It must be a png file. It is supported for Android < v12, iOS and the Web. 25 | #branding: assets/dart.png 26 | 27 | # To position the branding image at the bottom of the screen you can use bottom, bottomRight, 28 | # and bottomLeft. The default values is bottom if not specified or specified something else. 29 | #branding_mode: bottom 30 | 31 | # The color_dark, background_image_dark, image_dark, branding_dark are parameters that set the background 32 | # and image when the device is in dark mode. If they are not specified, the app will use the 33 | # parameters from above. If the image_dark parameter is specified, color_dark or 34 | # background_image_dark must be specified. color_dark and background_image_dark cannot both be 35 | # set. 36 | #color_dark: "#042a49" 37 | #background_image_dark: "assets/dark-background.png" 38 | #image_dark: assets/splash-invert.png 39 | #branding_dark: assets/dart_dark.png 40 | 41 | # Android 12 handles the splash screen differently than previous versions. Please visit 42 | # https://developer.android.com/guide/topics/ui/splash-screen 43 | # Following are Android 12 specific parameter. 44 | android_12: 45 | # The image parameter sets the splash screen icon image. If this parameter is not specified, 46 | # the app's launcher icon will be used instead. 47 | # Please note that the splash screen will be clipped to a circle on the center of the screen. 48 | # App icon with an icon background: This should be 960×960 pixels, and fit within a circle 49 | # 640 pixels in diameter. 50 | # App icon without an icon background: This should be 1152×1152 pixels, and fit within a circle 51 | # 768 pixels in diameter. 52 | #image: assets/android12splash.png 53 | 54 | # Splash screen background color. 55 | #color: "#42a5f5" 56 | 57 | # App icon background color. 58 | #icon_background_color: "#111111" 59 | 60 | # The image_dark parameter and icon_background_color_dark set the image and icon background 61 | # color when the device is in dark mode. If they are not specified, the app will use the 62 | # parameters from above. 63 | #image_dark: assets/android12splash-invert.png 64 | #color_dark: "#042a49" 65 | #icon_background_color_dark: "#eeeeee" 66 | 67 | # The android, ios and web parameters can be used to disable generating a splash screen on a given 68 | # platform. 69 | #android: false 70 | #ios: false 71 | #web: false 72 | 73 | # Platform specific images can be specified with the following parameters, which will override 74 | # the respective image parameter. You may specify all, selected, or none of these parameters: 75 | #image_andriod: assets/splash-andriod.png 76 | #image_dark_android: assets/splash-invert-android.png 77 | #image_ios: assets/splash-ios.png 78 | #image_dark_ios: assets/splash-invert-ios.png 79 | #image_web: assets/splash-web.png 80 | #image_dark_web: assets/splash-invert-web.png 81 | #background_image_android: "assets/background-android.png" 82 | #background_image_dark_android: "assets/dark-background-android.png" 83 | #background_image_ios: "assets/background-ios.png" 84 | #background_image_dark_ios: "assets/dark-background-ios.png" 85 | #background_image_web: "assets/background-web.png" 86 | #background_image_dark_web: "assets/dark-background-web.png" 87 | #branding_andriod: assets/brand-android.png 88 | #branding_dark_android: assets/dart_dark-android.png 89 | #branding_ios: assets/brand-ios.png 90 | #branding_dark_ios: assets/dart_dark-ios.png 91 | 92 | # The position of the splash image can be set with android_gravity, ios_content_mode, and 93 | # web_image_mode parameters. All default to center. 94 | # 95 | # android_gravity can be one of the following Android Gravity (see 96 | # https://developer.android.com/reference/android/view/Gravity): bottom, center, 97 | # center_horizontal, center_vertical, clip_horizontal, clip_vertical, end, fill, fill_horizontal, 98 | # fill_vertical, left, right, start, or top. 99 | #android_gravity: center 100 | # 101 | # ios_content_mode can be one of the following iOS UIView.ContentMode (see 102 | # https://developer.apple.com/documentation/uikit/uiview/contentmode): scaleToFill, 103 | # scaleAspectFit, scaleAspectFill, center, top, bottom, left, right, topLeft, topRight, 104 | # bottomLeft, or bottomRight. 105 | #ios_content_mode: center 106 | # 107 | # web_image_mode can be one of the following modes: center, contain, stretch, and cover. 108 | #web_image_mode: center 109 | 110 | # The screen orientation can be set in Android with the android_screen_orientation parameter. 111 | # Valid parameters can be found here: 112 | # https://developer.android.com/guide/topics/manifest/activity-element#screen 113 | #android_screen_orientation: sensorLandscape 114 | 115 | # To hide the notification bar, use the fullscreen parameter. Has no effect in web since web 116 | # has no notification bar. Defaults to false. 117 | # NOTE: Unlike Android, iOS will not automatically show the notification bar when the app loads. 118 | # To show the notification bar, add the following code to your Flutter app: 119 | # WidgetsFlutterBinding.ensureInitialized(); 120 | # SystemChrome.setEnabledSystemUIOverlays([SystemUiOverlay.bottom, SystemUiOverlay.top]); 121 | #fullscreen: true 122 | 123 | # If you have changed the name(s) of your info.plist file(s), you can specify the filename(s) 124 | # with the info_plist_files parameter. Remove only the # characters in the three lines below, 125 | # do not remove any spaces: 126 | #info_plist_files: 127 | # - 'ios/Runner/Info-Debug.plist' 128 | # - 'ios/Runner/Info-Release.plist' 129 | -------------------------------------------------------------------------------- /ios/.gitignore: -------------------------------------------------------------------------------- 1 | *.mode1v3 2 | *.mode2v3 3 | *.moved-aside 4 | *.pbxuser 5 | *.perspectivev3 6 | **/*sync/ 7 | .sconsign.dblite 8 | .tags* 9 | **/.vagrant/ 10 | **/DerivedData/ 11 | Icon? 12 | **/Pods/ 13 | **/.symlinks/ 14 | profile 15 | xcuserdata 16 | **/.generated/ 17 | Flutter/App.framework 18 | Flutter/Flutter.framework 19 | Flutter/Flutter.podspec 20 | Flutter/Generated.xcconfig 21 | Flutter/app.flx 22 | Flutter/app.zip 23 | Flutter/flutter_assets/ 24 | Flutter/flutter_export_environment.sh 25 | ServiceDefinitions.json 26 | Runner/GeneratedPluginRegistrant.* 27 | 28 | # Exceptions to above rules. 29 | !default.mode1v3 30 | !default.mode2v3 31 | !default.pbxuser 32 | !default.perspectivev3 33 | -------------------------------------------------------------------------------- /ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 11.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /ios/Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment this line to define a global platform for your project 2 | # platform :ios, '11.0' 3 | 4 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency. 5 | ENV['COCOAPODS_DISABLE_STATS'] = 'true' 6 | 7 | project 'Runner', { 8 | 'Debug' => :debug, 9 | 'Profile' => :release, 10 | 'Release' => :release, 11 | } 12 | 13 | def flutter_root 14 | generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) 15 | unless File.exist?(generated_xcode_build_settings_path) 16 | raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" 17 | end 18 | 19 | File.foreach(generated_xcode_build_settings_path) do |line| 20 | matches = line.match(/FLUTTER_ROOT\=(.*)/) 21 | return matches[1].strip if matches 22 | end 23 | raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" 24 | end 25 | 26 | require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) 27 | 28 | flutter_ios_podfile_setup 29 | 30 | target 'Runner' do 31 | use_frameworks! 32 | use_modular_headers! 33 | 34 | flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) 35 | target 'RunnerTests' do 36 | inherit! :search_paths 37 | end 38 | end 39 | 40 | post_install do |installer| 41 | installer.pods_project.targets.each do |target| 42 | flutter_additional_ios_build_settings(target) 43 | end 44 | end 45 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 37 | 38 | 39 | 40 | 43 | 49 | 50 | 51 | 54 | 60 | 61 | 62 | 63 | 64 | 74 | 76 | 82 | 83 | 84 | 85 | 91 | 93 | 99 | 100 | 101 | 102 | 104 | 105 | 108 | 109 | 110 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/xcshareddata/xcschemes/development.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 34 | 40 | 41 | 42 | 45 | 51 | 52 | 53 | 54 | 55 | 65 | 67 | 73 | 74 | 75 | 76 | 82 | 84 | 90 | 91 | 92 | 93 | 95 | 96 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/xcshareddata/xcschemes/production.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 34 | 40 | 41 | 42 | 45 | 51 | 52 | 53 | 54 | 55 | 65 | 67 | 73 | 74 | 75 | 76 | 82 | 84 | 90 | 91 | 92 | 93 | 95 | 96 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/xcshareddata/xcschemes/staging.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 34 | 40 | 41 | 42 | 45 | 51 | 52 | 53 | 54 | 55 | 65 | 67 | 73 | 74 | 75 | 76 | 82 | 84 | 90 | 91 | 92 | 93 | 95 | 96 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import Flutter 3 | 4 | @UIApplicationMain 5 | @objc class AppDelegate: FlutterAppDelegate { 6 | override func application( 7 | _ application: UIApplication, 8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? 9 | ) -> Bool { 10 | GeneratedPluginRegistrant.register(with: self) 11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon-dev.appiconset/100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon-dev.appiconset/100.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon-dev.appiconset/1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon-dev.appiconset/1024.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon-dev.appiconset/114.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon-dev.appiconset/114.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon-dev.appiconset/120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon-dev.appiconset/120.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon-dev.appiconset/128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon-dev.appiconset/128.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon-dev.appiconset/144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon-dev.appiconset/144.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon-dev.appiconset/152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon-dev.appiconset/152.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon-dev.appiconset/16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon-dev.appiconset/16.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon-dev.appiconset/167.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon-dev.appiconset/167.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon-dev.appiconset/172.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon-dev.appiconset/172.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon-dev.appiconset/180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon-dev.appiconset/180.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon-dev.appiconset/196.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon-dev.appiconset/196.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon-dev.appiconset/20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon-dev.appiconset/20.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon-dev.appiconset/216.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon-dev.appiconset/216.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon-dev.appiconset/256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon-dev.appiconset/256.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon-dev.appiconset/29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon-dev.appiconset/29.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon-dev.appiconset/32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon-dev.appiconset/32.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon-dev.appiconset/40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon-dev.appiconset/40.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon-dev.appiconset/48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon-dev.appiconset/48.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon-dev.appiconset/50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon-dev.appiconset/50.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon-dev.appiconset/512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon-dev.appiconset/512.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon-dev.appiconset/55.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon-dev.appiconset/55.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon-dev.appiconset/57.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon-dev.appiconset/57.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon-dev.appiconset/58.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon-dev.appiconset/58.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon-dev.appiconset/60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon-dev.appiconset/60.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon-dev.appiconset/64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon-dev.appiconset/64.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon-dev.appiconset/72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon-dev.appiconset/72.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon-dev.appiconset/76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon-dev.appiconset/76.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon-dev.appiconset/80.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon-dev.appiconset/80.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon-dev.appiconset/87.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon-dev.appiconset/87.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon-dev.appiconset/88.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon-dev.appiconset/88.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon-stg.appiconset/100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon-stg.appiconset/100.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon-stg.appiconset/1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon-stg.appiconset/1024.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon-stg.appiconset/114.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon-stg.appiconset/114.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon-stg.appiconset/120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon-stg.appiconset/120.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon-stg.appiconset/128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon-stg.appiconset/128.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon-stg.appiconset/144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon-stg.appiconset/144.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon-stg.appiconset/152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon-stg.appiconset/152.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon-stg.appiconset/16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon-stg.appiconset/16.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon-stg.appiconset/167.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon-stg.appiconset/167.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon-stg.appiconset/172.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon-stg.appiconset/172.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon-stg.appiconset/180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon-stg.appiconset/180.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon-stg.appiconset/196.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon-stg.appiconset/196.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon-stg.appiconset/20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon-stg.appiconset/20.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon-stg.appiconset/216.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon-stg.appiconset/216.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon-stg.appiconset/256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon-stg.appiconset/256.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon-stg.appiconset/29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon-stg.appiconset/29.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon-stg.appiconset/32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon-stg.appiconset/32.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon-stg.appiconset/40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon-stg.appiconset/40.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon-stg.appiconset/48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon-stg.appiconset/48.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon-stg.appiconset/50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon-stg.appiconset/50.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon-stg.appiconset/512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon-stg.appiconset/512.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon-stg.appiconset/55.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon-stg.appiconset/55.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon-stg.appiconset/57.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon-stg.appiconset/57.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon-stg.appiconset/58.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon-stg.appiconset/58.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon-stg.appiconset/60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon-stg.appiconset/60.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon-stg.appiconset/64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon-stg.appiconset/64.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon-stg.appiconset/72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon-stg.appiconset/72.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon-stg.appiconset/76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon-stg.appiconset/76.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon-stg.appiconset/80.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon-stg.appiconset/80.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon-stg.appiconset/87.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon-stg.appiconset/87.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon-stg.appiconset/88.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon-stg.appiconset/88.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon.appiconset/100.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon.appiconset/1024.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/114.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon.appiconset/114.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon.appiconset/120.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon.appiconset/128.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon.appiconset/144.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon.appiconset/152.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon.appiconset/16.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/167.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon.appiconset/167.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/172.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon.appiconset/172.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon.appiconset/180.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/196.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon.appiconset/196.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon.appiconset/20.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/216.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon.appiconset/216.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon.appiconset/256.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon.appiconset/29.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon.appiconset/32.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon.appiconset/40.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon.appiconset/48.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon.appiconset/50.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon.appiconset/512.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/55.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon.appiconset/55.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/57.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon.appiconset/57.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/58.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon.appiconset/58.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon.appiconset/60.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon.appiconset/64.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon.appiconset/72.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon.appiconset/76.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/80.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon.appiconset/80.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/87.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon.appiconset/87.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/88.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/AppIcon.appiconset/88.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "LaunchImage@1x.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "LaunchImage@2x.png", 10 | "idiom" : "universal", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "filename" : "LaunchImage@3x.png", 15 | "idiom" : "universal", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "author" : "xcode", 21 | "version" : 1 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md: -------------------------------------------------------------------------------- 1 | # Launch Screen Assets 2 | 3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory. 4 | 5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. -------------------------------------------------------------------------------- /ios/Runner/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /ios/Runner/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleLocalizations 6 | 7 | en 8 | es 9 | 10 | CFBundleDevelopmentRegion 11 | $(DEVELOPMENT_LANGUAGE) 12 | CFBundleDisplayName 13 | $(FLAVOR_APP_NAME) 14 | CFBundleExecutable 15 | $(EXECUTABLE_NAME) 16 | CFBundleIdentifier 17 | $(PRODUCT_BUNDLE_IDENTIFIER) 18 | CFBundleInfoDictionaryVersion 19 | 6.0 20 | CFBundleName 21 | Template 22 | CFBundlePackageType 23 | APPL 24 | CFBundleShortVersionString 25 | $(FLUTTER_BUILD_NAME) 26 | CFBundleSignature 27 | ???? 28 | CFBundleVersion 29 | $(FLUTTER_BUILD_NUMBER) 30 | LSRequiresIPhoneOS 31 | 32 | UILaunchStoryboardName 33 | LaunchScreen 34 | UIMainStoryboardFile 35 | Main 36 | UISupportedInterfaceOrientations 37 | 38 | UIInterfaceOrientationPortrait 39 | UIInterfaceOrientationLandscapeLeft 40 | UIInterfaceOrientationLandscapeRight 41 | 42 | UISupportedInterfaceOrientations~ipad 43 | 44 | UIInterfaceOrientationPortrait 45 | UIInterfaceOrientationPortraitUpsideDown 46 | UIInterfaceOrientationLandscapeLeft 47 | UIInterfaceOrientationLandscapeRight 48 | 49 | UIViewControllerBasedStatusBarAppearance 50 | 51 | CADisableMinimumFrameDurationOnPhone 52 | 53 | UIApplicationSupportsIndirectInputEvents 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" 2 | -------------------------------------------------------------------------------- /ios/RunnerTests/RunnerTests.swift: -------------------------------------------------------------------------------- 1 | import Flutter 2 | import UIKit 3 | import XCTest 4 | 5 | class RunnerTests: XCTestCase { 6 | 7 | func testExample() { 8 | // If you add code to the Runner application, consider adding tests here. 9 | // See https://developer.apple.com/documentation/xctest for more information about using XCTest. 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /l10n.yaml: -------------------------------------------------------------------------------- 1 | arb-dir: lib/l10n/arb 2 | template-arb-file: app_en.arb 3 | output-localization-file: app_localizations.dart 4 | nullable-getter: false 5 | -------------------------------------------------------------------------------- /lib/app/app.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, Adryan Eka Vandra 2 | // https://github.com/adryanev/flutter-template-architecture-template 3 | // 4 | // Use of this source code is governed by an MIT-style 5 | // license that can be found in the LICENSE file or at 6 | // https://opensource.org/licenses/MIT. 7 | 8 | export 'view/app.dart'; 9 | -------------------------------------------------------------------------------- /lib/app/router/app_router.dart: -------------------------------------------------------------------------------- 1 | import 'package:equatable/equatable.dart'; 2 | import 'package:flutter/foundation.dart'; 3 | import 'package:go_router/go_router.dart'; 4 | import 'package:template/features/counter/counter.dart'; 5 | 6 | class AppRouter extends Equatable { 7 | static const home = 'counter'; 8 | 9 | @override 10 | List get props => [home]; 11 | } 12 | 13 | GoRouter router([String? initialLocation]) => GoRouter( 14 | debugLogDiagnostics: kDebugMode || kProfileMode, 15 | initialLocation: initialLocation ?? '/', 16 | routes: [ 17 | GoRoute( 18 | path: '/', 19 | name: AppRouter.home, 20 | builder: (context, state) => const CounterPage(), 21 | ), 22 | ], 23 | ); 24 | -------------------------------------------------------------------------------- /lib/app/view/app.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, Adryan Eka Vandra 2 | // https://github.com/adryanev/flutter-template-architecture-template 3 | // 4 | // Use of this source code is governed by an MIT-style 5 | // license that can be found in the LICENSE file or at 6 | // https://opensource.org/licenses/MIT. 7 | 8 | import 'package:flutter/material.dart'; 9 | import 'package:flutter_bloc/flutter_bloc.dart'; 10 | import 'package:flutter_localizations/flutter_localizations.dart'; 11 | import 'package:flutter_screenutil/flutter_screenutil.dart'; 12 | import 'package:google_fonts/google_fonts.dart'; 13 | import 'package:template/app/router/app_router.dart'; 14 | import 'package:template/core/extensions/context_extensions.dart'; 15 | import 'package:template/core/utils/constants.dart'; 16 | import 'package:template/injector.dart'; 17 | import 'package:template/l10n/l10n.dart'; 18 | import 'package:template/shared/flash/presentation/blocs/cubit/flash_cubit.dart'; 19 | 20 | class App extends StatelessWidget { 21 | const App({super.key}); 22 | 23 | @override 24 | Widget build(BuildContext context) { 25 | return MultiBlocProvider( 26 | providers: [ 27 | BlocProvider( 28 | create: (context) => getIt(), 29 | ), 30 | ], 31 | child: MultiBlocListener( 32 | listeners: [ 33 | BlocListener( 34 | listener: (context, state) { 35 | switch (state) { 36 | case FlashDisappeared(): 37 | break; 38 | case FlashAppeared(): 39 | context.showSnackbar( 40 | message: state.message, 41 | ); 42 | } 43 | }, 44 | ), 45 | ], 46 | child: ScreenUtilInit( 47 | designSize: const Size(ScreenUtilSize.width, ScreenUtilSize.height), 48 | builder: (context, child) { 49 | return MaterialApp.router( 50 | scaffoldMessengerKey: rootScaffoldMessengerKey, 51 | theme: ThemeData( 52 | useMaterial3: true, 53 | fontFamily: GoogleFonts.poppins().fontFamily, 54 | ), 55 | localizationsDelegates: const [ 56 | AppLocalizations.delegate, 57 | GlobalMaterialLocalizations.delegate, 58 | ], 59 | supportedLocales: AppLocalizations.supportedLocales, 60 | routerConfig: router(), 61 | builder: (context, widget) { 62 | return MediaQuery( 63 | data: MediaQuery.of(context) 64 | .copyWith(textScaler: TextScaler.noScaling), 65 | child: widget!, 66 | ); 67 | }, 68 | ); 69 | }, 70 | ), 71 | ), 72 | ); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /lib/bootstrap.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, Adryan Eka Vandra 2 | // https://github.com/adryanev/flutter-template-architecture-template 3 | // 4 | // Use of this source code is governed by an MIT-style 5 | // license that can be found in the LICENSE file or at 6 | // https://opensource.org/licenses/MIT. 7 | 8 | import 'dart:async'; 9 | import 'dart:developer'; 10 | 11 | import 'package:bloc/bloc.dart'; 12 | import 'package:flutter/widgets.dart'; 13 | import 'package:template/injector.dart'; 14 | 15 | class AppBlocObserver extends BlocObserver { 16 | @override 17 | void onChange(BlocBase bloc, Change change) { 18 | super.onChange(bloc, change); 19 | log('onChange(${bloc.runtimeType}, $change)'); 20 | } 21 | 22 | @override 23 | void onError(BlocBase bloc, Object error, StackTrace stackTrace) { 24 | log('onError(${bloc.runtimeType}, $error, $stackTrace)'); 25 | super.onError(bloc, error, stackTrace); 26 | } 27 | } 28 | 29 | Future bootstrap( 30 | FutureOr Function() builder, { 31 | required String environment, 32 | }) async { 33 | WidgetsFlutterBinding.ensureInitialized(); 34 | 35 | await configureDependencies(environment: environment); 36 | FlutterError.onError = (details) { 37 | log(details.exceptionAsString(), stackTrace: details.stack); 38 | }; 39 | 40 | Bloc.observer = AppBlocObserver(); 41 | 42 | runApp(await builder()); 43 | } 44 | -------------------------------------------------------------------------------- /lib/core/di/app_module.dart: -------------------------------------------------------------------------------- 1 | import 'package:injectable/injectable.dart'; 2 | 3 | @module 4 | abstract class AppModule {} 5 | -------------------------------------------------------------------------------- /lib/core/di/storage_module.dart: -------------------------------------------------------------------------------- 1 | import 'package:injectable/injectable.dart'; 2 | import 'package:shared_preferences/shared_preferences.dart'; 3 | 4 | @module 5 | abstract class StorageModule { 6 | @lazySingleton 7 | @preResolve 8 | Future get sharedPreference async => 9 | SharedPreferences.getInstance(); 10 | } 11 | -------------------------------------------------------------------------------- /lib/core/domain/entities/value_object.dart: -------------------------------------------------------------------------------- 1 | import 'package:dartz/dartz.dart'; 2 | import 'package:meta/meta.dart'; 3 | import 'package:template/core/domain/failures/errors.dart'; 4 | import 'package:template/core/domain/failures/value_failure.dart'; 5 | 6 | // ignore: one_member_abstracts 7 | abstract class IValidatable { 8 | bool isValid(); 9 | } 10 | 11 | @immutable 12 | abstract class ValueObject implements IValidatable { 13 | const ValueObject(); 14 | Either, T> get value; 15 | 16 | T getOrCrash() => value.fold((l) => throw UnexpectedValueError(l), id); 17 | 18 | T getOrElse(T dflt) => value.getOrElse(() => dflt); 19 | 20 | Either, Unit> get failureOrUnit => 21 | value.fold(left, (r) => right(unit)); 22 | 23 | @override 24 | bool isValid() => value.isRight(); 25 | 26 | @override 27 | bool operator ==(Object other) { 28 | if (identical(this, other)) return true; 29 | return other is ValueObject && other.value == value; 30 | } 31 | 32 | @override 33 | int get hashCode => value.hashCode; 34 | 35 | @override 36 | String toString() => 'Value($value)'; 37 | } 38 | -------------------------------------------------------------------------------- /lib/core/domain/entities/value_validators.dart: -------------------------------------------------------------------------------- 1 | import 'package:dartz/dartz.dart'; 2 | import 'package:template/core/domain/failures/value_failure.dart'; 3 | 4 | Either, String> validateStringNotEmpty(String input) { 5 | if (input.isEmpty) { 6 | return left(ValueFailure.empty(failedValue: input)); 7 | } else { 8 | return right(input); 9 | } 10 | } 11 | 12 | Either, String> validateSingleLine(String input) { 13 | if (input.contains('\n')) { 14 | return left(ValueFailure.multiLine(failedValue: input)); 15 | } else { 16 | return right(input); 17 | } 18 | } 19 | 20 | Either, T> validateNumberRange({ 21 | required T minimum, 22 | required T maximum, 23 | required T number, 24 | }) { 25 | if (number > maximum || number < minimum) { 26 | return left( 27 | ValueFailure.notInRange( 28 | failedValue: number, 29 | minimum: minimum, 30 | maximum: maximum, 31 | ), 32 | ); 33 | } else { 34 | return right(number); 35 | } 36 | } 37 | 38 | Either, String> validateUniqueId(String input) { 39 | final regex = RegExp( 40 | '^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}', 41 | ); 42 | if (regex.hasMatch(input)) { 43 | return right(input); 44 | } 45 | return left(ValueFailure.invalidUniqueId(failedValue: input)); 46 | } 47 | -------------------------------------------------------------------------------- /lib/core/domain/failures/errors.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: strict_raw_type 2 | 3 | import 'package:template/core/domain/failures/value_failure.dart'; 4 | 5 | class UnexpectedValueError extends Error { 6 | UnexpectedValueError(this.valueFailure); 7 | final ValueFailure valueFailure; 8 | 9 | @override 10 | String toString() { 11 | const explanation = 12 | 'Encountered a ValueFailure at an unrecoverable point. Terminating.'; 13 | return Error.safeToString('$explanation Failure was: $valueFailure'); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /lib/core/domain/failures/failure.dart: -------------------------------------------------------------------------------- 1 | sealed class Failure { 2 | const Failure(); 3 | const factory Failure.localFailure({required String message}) = LocalFailure; 4 | const factory Failure.serverFailure({required String message}) = 5 | ServerFailure; 6 | } 7 | 8 | class LocalFailure extends Failure { 9 | const LocalFailure({required this.message}); 10 | final String message; 11 | } 12 | 13 | class ServerFailure extends Failure { 14 | const ServerFailure({required this.message}); 15 | final String message; 16 | } 17 | -------------------------------------------------------------------------------- /lib/core/domain/failures/value_failure.dart: -------------------------------------------------------------------------------- 1 | sealed class ValueFailure { 2 | const ValueFailure(); 3 | const factory ValueFailure.notInRange({ 4 | required T failedValue, 5 | required T minimum, 6 | required T maximum, 7 | }) = ValueFailureNotInRange; 8 | 9 | const factory ValueFailure.invalidUniqueId({ 10 | required T failedValue, 11 | }) = ValueFailureInvalidUniqueId; 12 | const factory ValueFailure.empty({required T failedValue}) = 13 | ValueFailureEmpty; 14 | const factory ValueFailure.multiLine({required T failedValue}) = 15 | ValueFailureMultiLine; 16 | } 17 | 18 | class ValueFailureEmpty extends ValueFailure { 19 | const ValueFailureEmpty({required this.failedValue}); 20 | final T failedValue; 21 | 22 | @override 23 | String toString() { 24 | return 'ValueFailure<$T>.empty(failedValue: $failedValue)'; 25 | } 26 | } 27 | 28 | class ValueFailureMultiLine extends ValueFailure { 29 | const ValueFailureMultiLine({required this.failedValue}); 30 | final T failedValue; 31 | 32 | @override 33 | String toString() { 34 | return 'ValueFailure<$T>.multiLine(failedValue: $failedValue)'; 35 | } 36 | } 37 | 38 | class ValueFailureNotInRange extends ValueFailure { 39 | const ValueFailureNotInRange({ 40 | required this.failedValue, 41 | required this.minimum, 42 | required this.maximum, 43 | }); 44 | final T failedValue; 45 | final T minimum; 46 | final T maximum; 47 | 48 | @override 49 | String toString() { 50 | return 'ValueFailure<$T>.notInRange' 51 | '(failedValue: $failedValue, minimum: $minimum, maximum: $maximum)'; 52 | } 53 | } 54 | 55 | class ValueFailureInvalidUniqueId extends ValueFailure { 56 | const ValueFailureInvalidUniqueId({required this.failedValue}); 57 | final T failedValue; 58 | 59 | @override 60 | String toString() { 61 | return 'ValueFailure<$T>.invalidUniqueId(failedValue: $failedValue)'; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /lib/core/domain/usecases/use_case.dart: -------------------------------------------------------------------------------- 1 | import 'package:dartz/dartz.dart'; 2 | import 'package:equatable/equatable.dart'; 3 | import 'package:template/core/domain/failures/failure.dart'; 4 | 5 | abstract class UseCase { 6 | const UseCase(); 7 | Future> call(Params params); 8 | } 9 | 10 | abstract class StreamUseCase { 11 | const StreamUseCase(); 12 | Stream> call(Params params); 13 | } 14 | 15 | class NoParams extends Equatable { 16 | @override 17 | List get props => []; 18 | } 19 | -------------------------------------------------------------------------------- /lib/core/extensions/context_extensions.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_bloc/flutter_bloc.dart'; 3 | import 'package:template/core/utils/constants.dart'; 4 | import 'package:template/shared/flash/presentation/blocs/cubit/flash_cubit.dart'; 5 | 6 | extension BuildContextX on BuildContext { 7 | void displayFlash(String message) { 8 | read().displayFlash(message); 9 | } 10 | 11 | void showSnackbar({ 12 | required String message, 13 | void Function()? action, 14 | String? actionText, 15 | }) { 16 | rootScaffoldMessengerKey.currentState?.showSnackBar( 17 | SnackBar( 18 | content: Text(message), 19 | duration: const Duration(seconds: 2), 20 | // action: action == null && actionText != null 21 | // ? null 22 | // : SnackBarAction(label: actionText!, onPressed: action!), 23 | ), 24 | ); 25 | } 26 | 27 | ThemeData get theme => Theme.of(this); 28 | } 29 | -------------------------------------------------------------------------------- /lib/core/extensions/dartz_extensions.dart: -------------------------------------------------------------------------------- 1 | import 'package:dartz/dartz.dart'; 2 | 3 | // get Left and Right value 4 | extension EitherX on Either { 5 | R? getRight() => fold((_) => null, (r) => r); 6 | L? getLeft() => fold((l) => l, (_) => null); 7 | 8 | R? unwrapRight() { 9 | return toOption().toNullable(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /lib/core/presentation/mixins/failure_message_handler.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:template/core/domain/failures/failure.dart'; 3 | import 'package:template/core/extensions/context_extensions.dart'; 4 | // import 'package:template/l10n/l10n.dart'; 5 | 6 | mixin FailureMessageHandler { 7 | void handleFailure(BuildContext context, Failure failure) { 8 | switch (failure) { 9 | case LocalFailure(): 10 | context.displayFlash(failure.message); 11 | case ServerFailure(): 12 | context.displayFlash(failure.message); 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /lib/core/storages/local_storages.dart: -------------------------------------------------------------------------------- 1 | import 'package:injectable/injectable.dart'; 2 | import 'package:shared_preferences/shared_preferences.dart'; 3 | 4 | abstract class LocalStorage { 5 | Future getApiKey(); 6 | Future setApiKey(String apiKey); 7 | } 8 | 9 | @LazySingleton(as: LocalStorage) 10 | class LocalStorageImpl implements LocalStorage { 11 | const LocalStorageImpl(this._storage); 12 | final SharedPreferences _storage; 13 | static const _apiKeyKey = 'apiKey'; 14 | 15 | @override 16 | Future getApiKey() { 17 | return Future.value( 18 | _storage.getString(_apiKeyKey), 19 | ); 20 | } 21 | 22 | @override 23 | Future setApiKey(String apiKey) async { 24 | await Future.value( 25 | _storage.setString(_apiKeyKey, apiKey), 26 | ); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /lib/core/utils/colors.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class AppColor { 4 | static const primary = Color(0xFF006BB3); 5 | static const blueLightest = Color(0xFFD7F4FE); 6 | static const blueLighter = Color(0xFFAAD9E9); 7 | static const blue = Color(0xFF62B8F6); 8 | static const blueDark = Color(0xFF3C99DD); 9 | static const blueDarker = Color(0xFF2C79C1); 10 | static const blueDarkest = Color(0xFF1B2541); 11 | static const white = Color(0xFFFFFFFF); 12 | 13 | static const pink = Color(0xFFFEE3D7); 14 | static const brownLight = Color(0xFFE9C8AA); 15 | static const orange = Color(0xFFF69762); 16 | static const orangeDark = Color(0xFFDD893C); 17 | static const orangeDarkest = Color(0xFFC1502C); 18 | 19 | static const blueBackgroundGradient = LinearGradient( 20 | begin: Alignment.topCenter, 21 | end: Alignment.bottomCenter, 22 | colors: [blue, blueDarker], 23 | stops: [ 24 | 0, 25 | 0.7, 26 | ], 27 | ); 28 | } 29 | -------------------------------------------------------------------------------- /lib/core/utils/constants.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:intl/intl.dart'; 3 | 4 | class Environment { 5 | const Environment._(); 6 | static const String development = 'development'; 7 | static const String staging = 'staging'; 8 | static const String production = 'production'; 9 | static const String test = 'test'; 10 | } 11 | 12 | class ScreenUtilSize { 13 | const ScreenUtilSize._(); 14 | static const double width = 390; 15 | static const double height = 844; 16 | } 17 | 18 | final GlobalKey rootScaffoldMessengerKey = 19 | GlobalKey(); 20 | 21 | class DateTimeFormat { 22 | static DateFormat get dayString => DateFormat.EEEE(); 23 | static DateFormat get monthAbbrWithDate => DateFormat.MMMMd(); 24 | static DateFormat get hourMinutes => DateFormat.Hm(); 25 | } 26 | 27 | enum MessageType { 28 | info, 29 | warning, 30 | success, 31 | danger, 32 | } 33 | -------------------------------------------------------------------------------- /lib/core/utils/dimensions.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_screenutil/flutter_screenutil.dart'; 3 | 4 | class Dimension { 5 | static final horizontalPadding = EdgeInsets.symmetric( 6 | horizontal: 16.w, 7 | ); 8 | static final verticalPadding = EdgeInsets.symmetric( 9 | vertical: 16.h, 10 | ); 11 | static final aroundPadding = EdgeInsets.symmetric( 12 | horizontal: 16.w, 13 | vertical: 16.h, 14 | ); 15 | } 16 | -------------------------------------------------------------------------------- /lib/features/counter/counter.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, Adryan Eka Vandra 2 | // https://github.com/adryanev/flutter-template-architecture-template 3 | // 4 | // Use of this source code is governed by an MIT-style 5 | // license that can be found in the LICENSE file or at 6 | // https://opensource.org/licenses/MIT. 7 | 8 | export 'presentation/blocs/counter_cubit.dart'; 9 | export 'presentation/pages/counter_page.dart'; 10 | -------------------------------------------------------------------------------- /lib/features/counter/data/datasources/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/lib/features/counter/data/datasources/.gitkeep -------------------------------------------------------------------------------- /lib/features/counter/data/models/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/lib/features/counter/data/models/.gitkeep -------------------------------------------------------------------------------- /lib/features/counter/data/repositories/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/lib/features/counter/data/repositories/.gitkeep -------------------------------------------------------------------------------- /lib/features/counter/domain/entities/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/lib/features/counter/domain/entities/.gitkeep -------------------------------------------------------------------------------- /lib/features/counter/domain/repositories/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/lib/features/counter/domain/repositories/.gitkeep -------------------------------------------------------------------------------- /lib/features/counter/domain/usecases/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/lib/features/counter/domain/usecases/.gitkeep -------------------------------------------------------------------------------- /lib/features/counter/presentation/blocs/counter_cubit.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, Adryan Eka Vandra 2 | // https://github.com/adryanev/flutter-template-architecture-template 3 | // 4 | // Use of this source code is governed by an MIT-style 5 | // license that can be found in the LICENSE file or at 6 | // https://opensource.org/licenses/MIT. 7 | 8 | import 'package:bloc/bloc.dart'; 9 | import 'package:injectable/injectable.dart'; 10 | 11 | @injectable 12 | class CounterCubit extends Cubit { 13 | CounterCubit() : super(0); 14 | 15 | void increment() => emit(state + 1); 16 | void decrement() => emit(state - 1); 17 | } 18 | -------------------------------------------------------------------------------- /lib/features/counter/presentation/pages/counter_page.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, Adryan Eka Vandra 2 | // https://github.com/adryanev/flutter-template-architecture-template 3 | // 4 | // Use of this source code is governed by an MIT-style 5 | // license that can be found in the LICENSE file or at 6 | // https://opensource.org/licenses/MIT. 7 | 8 | import 'package:flutter/material.dart'; 9 | import 'package:flutter_bloc/flutter_bloc.dart'; 10 | import 'package:template/core/extensions/context_extensions.dart'; 11 | import 'package:template/core/presentation/mixins/failure_message_handler.dart'; 12 | import 'package:template/features/counter/counter.dart'; 13 | import 'package:template/l10n/l10n.dart'; 14 | 15 | class CounterPage extends StatelessWidget with FailureMessageHandler { 16 | const CounterPage({super.key}); 17 | 18 | @override 19 | Widget build(BuildContext context) { 20 | return BlocProvider( 21 | create: (_) => CounterCubit(), 22 | child: const CounterView(), 23 | ); 24 | } 25 | } 26 | 27 | class CounterView extends StatelessWidget { 28 | const CounterView({super.key}); 29 | 30 | @override 31 | Widget build(BuildContext context) { 32 | final l10n = context.l10n; 33 | return Scaffold( 34 | appBar: AppBar(title: Text(l10n.counterAppBarTitle)), 35 | body: const Center(child: CounterText()), 36 | floatingActionButton: Column( 37 | mainAxisAlignment: MainAxisAlignment.end, 38 | crossAxisAlignment: CrossAxisAlignment.end, 39 | children: [ 40 | FloatingActionButton( 41 | onPressed: () => context.read().increment(), 42 | child: const Icon(Icons.add), 43 | ), 44 | const SizedBox(height: 8), 45 | FloatingActionButton( 46 | onPressed: () => context.read().decrement(), 47 | child: const Icon(Icons.remove), 48 | ), 49 | ], 50 | ), 51 | ); 52 | } 53 | } 54 | 55 | class CounterText extends StatelessWidget { 56 | const CounterText({super.key}); 57 | 58 | @override 59 | Widget build(BuildContext context) { 60 | final count = context.select((CounterCubit cubit) => cubit.state); 61 | return Text('$count', style: context.theme.textTheme.displayLarge); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /lib/features/counter/presentation/widgets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/lib/features/counter/presentation/widgets/.gitkeep -------------------------------------------------------------------------------- /lib/injector.dart: -------------------------------------------------------------------------------- 1 | import 'package:get_it/get_it.dart'; 2 | import 'package:injectable/injectable.dart'; 3 | import 'package:template/injector.config.dart'; 4 | 5 | final getIt = GetIt.instance; 6 | 7 | @InjectableInit(generateForDir: ['lib', 'test']) 8 | Future configureDependencies({required String environment}) async => 9 | getIt.init(environment: environment); 10 | -------------------------------------------------------------------------------- /lib/l10n/arb/app_en.arb: -------------------------------------------------------------------------------- 1 | { 2 | "@@locale": "en", 3 | "counterAppBarTitle": "Counter", 4 | "@counterAppBarTitle": { 5 | "description": "Text shown in the AppBar of the Counter Page" 6 | }, 7 | "invalidEmail": "Invalid Email Address", 8 | "invalidPassword": "Password must be at least 8 characters and contain at least one letter and number", 9 | "confirmPasswordMismatch": "Password confirmation not match" 10 | } 11 | -------------------------------------------------------------------------------- /lib/l10n/arb/app_id.arb: -------------------------------------------------------------------------------- 1 | { 2 | "@@locale": "id", 3 | "counterAppBarTitle": "Penghitung", 4 | "@counterAppBarTitle": { 5 | "description": "Teks yang tampil pada AppBar di Halaman Counter" 6 | }, 7 | "invalidEmail": "Alamat Email tidak valid", 8 | "invalidPassword": "Password harus terdiri dari 8 karakter yang terdiri dari huruf dan angka.", 9 | "confirmPasswordMismatch": "Konfirmasi password tidak cocok." 10 | } 11 | -------------------------------------------------------------------------------- /lib/l10n/l10n.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, Adryan Eka Vandra 2 | // https://github.com/adryanev/flutter-template-architecture-template 3 | // 4 | // Use of this source code is governed by an MIT-style 5 | // license that can be found in the LICENSE file or at 6 | // https://opensource.org/licenses/MIT. 7 | 8 | import 'package:flutter/widgets.dart'; 9 | import 'package:flutter_gen/gen_l10n/app_localizations.dart'; 10 | 11 | export 'package:flutter_gen/gen_l10n/app_localizations.dart'; 12 | 13 | extension AppLocalizationsX on BuildContext { 14 | AppLocalizations get l10n => AppLocalizations.of(this); 15 | } 16 | -------------------------------------------------------------------------------- /lib/main_development.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, Adryan Eka Vandra 2 | // https://github.com/adryanev/flutter-template-architecture-template 3 | // 4 | // Use of this source code is governed by an MIT-style 5 | // license that can be found in the LICENSE file or at 6 | // https://opensource.org/licenses/MIT. 7 | 8 | import 'package:template/app/app.dart'; 9 | import 'package:template/bootstrap.dart'; 10 | import 'package:template/core/utils/constants.dart'; 11 | 12 | void main() { 13 | bootstrap(() => const App(), environment: Environment.development); 14 | } 15 | -------------------------------------------------------------------------------- /lib/main_production.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, Adryan Eka Vandra 2 | // https://github.com/adryanev/flutter-template-architecture-template 3 | // 4 | // Use of this source code is governed by an MIT-style 5 | // license that can be found in the LICENSE file or at 6 | // https://opensource.org/licenses/MIT. 7 | 8 | import 'package:template/app/app.dart'; 9 | import 'package:template/bootstrap.dart'; 10 | import 'package:template/core/utils/constants.dart'; 11 | 12 | void main() { 13 | bootstrap(() => const App(), environment: Environment.production); 14 | } 15 | -------------------------------------------------------------------------------- /lib/main_staging.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, Adryan Eka Vandra 2 | // https://github.com/adryanev/flutter-template-architecture-template 3 | // 4 | // Use of this source code is governed by an MIT-style 5 | // license that can be found in the LICENSE file or at 6 | // https://opensource.org/licenses/MIT. 7 | 8 | import 'package:template/app/app.dart'; 9 | import 'package:template/bootstrap.dart'; 10 | import 'package:template/core/utils/constants.dart'; 11 | 12 | void main() { 13 | bootstrap(() => const App(), environment: Environment.staging); 14 | } 15 | -------------------------------------------------------------------------------- /lib/shared/domain/entities/value_objects.dart: -------------------------------------------------------------------------------- 1 | import 'package:dartz/dartz.dart'; 2 | import 'package:template/core/domain/entities/value_object.dart'; 3 | import 'package:template/core/domain/entities/value_validators.dart'; 4 | import 'package:template/core/domain/failures/value_failure.dart'; 5 | import 'package:uuid/uuid.dart'; 6 | 7 | class UniqueId extends ValueObject { 8 | factory UniqueId(String input) { 9 | return UniqueId._(validateUniqueId(input)); 10 | } 11 | 12 | factory UniqueId.generate() { 13 | return UniqueId._( 14 | validateUniqueId( 15 | const Uuid().v4(), 16 | ), 17 | ); 18 | } 19 | const UniqueId._(this.value); 20 | @override 21 | final Either, String> value; 22 | } 23 | 24 | class StringSingleLine extends ValueObject { 25 | factory StringSingleLine(String input) { 26 | return StringSingleLine._( 27 | validateStringNotEmpty(input).flatMap(validateSingleLine), 28 | ); 29 | } 30 | 31 | const StringSingleLine._(this.value); 32 | 33 | @override 34 | final Either, String> value; 35 | } 36 | -------------------------------------------------------------------------------- /lib/shared/domain/formz/email_input.dart: -------------------------------------------------------------------------------- 1 | import 'package:formz/formz.dart'; 2 | import 'package:template/l10n/l10n.dart'; 3 | 4 | enum EmailValidationError { invalid } 5 | 6 | class EmailInput extends FormzInput { 7 | const EmailInput.pure([super.value = '']) : super.pure(); 8 | const EmailInput.dirty([super.value = '']) : super.dirty(); 9 | 10 | static final _emailRegExp = RegExp( 11 | r'^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$', 12 | ); 13 | 14 | @override 15 | EmailValidationError? validator(String value) { 16 | return _emailRegExp.hasMatch(value) ? null : EmailValidationError.invalid; 17 | } 18 | } 19 | 20 | extension on EmailValidationError { 21 | // ignore: unused_element 22 | String errorMessage(AppLocalizations i10n) { 23 | switch (this) { 24 | case EmailValidationError.invalid: 25 | return i10n.invalidEmail; 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /lib/shared/domain/formz/password_confirmation_input.dart: -------------------------------------------------------------------------------- 1 | import 'package:formz/formz.dart'; 2 | import 'package:template/l10n/l10n.dart'; 3 | 4 | enum PasswordConfirmationValidationError { mismatch } 5 | 6 | class PasswordConfirmationInput 7 | extends FormzInput { 8 | const PasswordConfirmationInput.pure([super.value = '', this._password = '']) 9 | : super.pure(); 10 | const PasswordConfirmationInput.dirty(this._password, [super.value = '']) 11 | : super.dirty(); 12 | 13 | final String _password; 14 | @override 15 | PasswordConfirmationValidationError? validator(String value) { 16 | if (_password != value) { 17 | return PasswordConfirmationValidationError.mismatch; 18 | } 19 | return null; 20 | } 21 | } 22 | 23 | extension on PasswordConfirmationValidationError { 24 | // ignore: unused_element 25 | String errorMessage(AppLocalizations i10n) { 26 | switch (this) { 27 | case PasswordConfirmationValidationError.mismatch: 28 | return i10n.confirmPasswordMismatch; 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /lib/shared/domain/formz/password_input.dart: -------------------------------------------------------------------------------- 1 | import 'package:formz/formz.dart'; 2 | import 'package:template/l10n/l10n.dart'; 3 | 4 | enum PasswordValidationError { invalid } 5 | 6 | class PasswordInput extends FormzInput { 7 | const PasswordInput.pure([super.value = '']) : super.pure(); 8 | const PasswordInput.dirty([super.value = '']) : super.dirty(); 9 | 10 | static final _passwordRegex = 11 | RegExp(r'^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]{8,}$'); 12 | 13 | @override 14 | PasswordValidationError? validator(String value) { 15 | return _passwordRegex.hasMatch(value) 16 | ? null 17 | : PasswordValidationError.invalid; 18 | } 19 | } 20 | 21 | extension on PasswordValidationError { 22 | // ignore: unused_element 23 | String errorMessage(AppLocalizations i10n) { 24 | switch (this) { 25 | case PasswordValidationError.invalid: 26 | return i10n.invalidPassword; 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /lib/shared/flash/presentation/blocs/cubit/flash_cubit.dart: -------------------------------------------------------------------------------- 1 | import 'package:bloc/bloc.dart'; 2 | import 'package:injectable/injectable.dart'; 3 | 4 | part 'flash_state.dart'; 5 | 6 | @injectable 7 | class FlashCubit extends Cubit { 8 | FlashCubit() : super(const FlashState.disappeared()); 9 | 10 | Future displayFlash(String message) async { 11 | emit(FlashState.appeared(message)); 12 | emit(const FlashState.disappeared()); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /lib/shared/flash/presentation/blocs/cubit/flash_state.dart: -------------------------------------------------------------------------------- 1 | part of 'flash_cubit.dart'; 2 | 3 | sealed class FlashState { 4 | const FlashState(); 5 | const factory FlashState.disappeared() = FlashDisappeared; 6 | const factory FlashState.appeared(String message) = FlashAppeared; 7 | } 8 | 9 | class FlashDisappeared extends FlashState { 10 | const FlashDisappeared(); 11 | } 12 | 13 | class FlashAppeared extends FlashState { 14 | const FlashAppeared(this.message); 15 | final String message; 16 | } 17 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: template 2 | description: A template Flutter Project 3 | version: 1.0.0+1 4 | publish_to: none 5 | 6 | environment: 7 | sdk: ">=3.6.0 <4.0.0" 8 | 9 | dependencies: 10 | bloc: ^8.1.4 11 | change_case: ^2.1.0 12 | collection: ^1.19.1 13 | crypto: ^3.0.6 14 | cupertino_icons: ^1.0.8 15 | dartz: ^0.10.1 16 | equatable: ^2.0.7 17 | flutter: 18 | sdk: flutter 19 | flutter_bloc: ^8.1.6 20 | flutter_localizations: 21 | sdk: flutter 22 | flutter_native_splash: ^2.4.3 23 | flutter_screenutil: ^5.9.3 24 | formz: ^0.8.0 25 | get_it: ^8.0.3 26 | go_router: ^14.6.2 27 | google_fonts: ^6.2.1 28 | injectable: ^2.5.0 29 | intl: ^0.20.1 30 | json_annotation: ^4.9.0 31 | meta: ^1.16.0 32 | rxdart: ^0.28.0 33 | shared_preferences: ^2.3.4 34 | uuid: ^4.5.1 35 | 36 | dev_dependencies: 37 | bloc_test: ^9.1.7 38 | build_runner: ^2.4.14 39 | flutter_gen_runner: ^5.8.0 40 | flutter_test: 41 | sdk: flutter 42 | injectable_generator: ^2.6.2 43 | mocktail: ^1.0.4 44 | very_good_analysis: ^7.0.0 45 | 46 | dependency_overrides: 47 | collection: ^1.19.1 48 | intl: ^0.20.1 49 | meta: ^1.16.0 50 | 51 | flutter_gen: 52 | output: lib/gen/ # Optional (default: lib/gen/) 53 | line_length: 80 # Optional (default: 80) 54 | 55 | # Optional 56 | integrations: 57 | flutter_svg: true 58 | # flare_flutter: true 59 | # rive: true 60 | 61 | flutter: 62 | uses-material-design: true 63 | generate: true 64 | 65 | assets: 66 | - assets/fonts/ 67 | - assets/google_fonts/ 68 | - assets/icons/ 69 | - assets/images/ 70 | -------------------------------------------------------------------------------- /test/app/view/app_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, Adryan Eka Vandra 2 | // https://github.com/adryanev/flutter-template-architecture-template 3 | // 4 | // Use of this source code is governed by an MIT-style 5 | // license that can be found in the LICENSE file or at 6 | // https://opensource.org/licenses/MIT. 7 | 8 | import 'package:flutter/material.dart'; 9 | import 'package:flutter_test/flutter_test.dart'; 10 | import 'package:google_fonts/google_fonts.dart'; 11 | import 'package:shared_preferences/shared_preferences.dart'; 12 | 13 | import '../../helpers/helpers.dart'; 14 | 15 | void main() { 16 | setUpAll(() async { 17 | SharedPreferences.setMockInitialValues({}); 18 | await configureInjector(); 19 | }); 20 | 21 | setUp(() => GoogleFonts.config.allowRuntimeFetching = false); 22 | group('App', () { 23 | testWidgets('renders CounterPage', (tester) async { 24 | await tester.pumpAppRouter( 25 | '/', 26 | (child) => child, 27 | isConnected: false, 28 | ); 29 | expect(find.byType(MaterialApp, skipOffstage: false), findsOneWidget); 30 | }); 31 | }); 32 | } 33 | -------------------------------------------------------------------------------- /test/core/domain/entities/value_object_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:dartz/dartz.dart'; 2 | import 'package:flutter_test/flutter_test.dart'; 3 | import 'package:template/core/domain/entities/value_object.dart'; 4 | import 'package:template/core/domain/failures/errors.dart'; 5 | import 'package:template/core/domain/failures/value_failure.dart'; 6 | 7 | // Define a subclass of ValueObject for testing purposes 8 | class TestValueObject extends ValueObject { 9 | const TestValueObject(this.value); 10 | @override 11 | final Either, String> value; 12 | } 13 | 14 | void main() { 15 | // Define a group of tests for the ValueObject class 16 | group('ValueObject', () { 17 | // Define a test case for the IValidatable interface 18 | test('should implement IValidatable interface', () { 19 | // Create a valid and an invalid TestValueObject 20 | final valid = TestValueObject(right('valid')); 21 | final invalid = TestValueObject( 22 | left( 23 | const ValueFailure.empty(failedValue: 'invalid'), 24 | ), 25 | ); 26 | 27 | // Assert that they implement IValidatable interface 28 | expect(valid, isA()); 29 | expect(invalid, isA()); 30 | }); 31 | 32 | // Define a test case for the getOrCrash method 33 | test('getOrCrash should return the value or throw an exception', () { 34 | // Create a valid and an invalid TestValueObject 35 | final valid = TestValueObject(right('valid')); 36 | final invalid = TestValueObject( 37 | left( 38 | const ValueFailure.empty(failedValue: 'invalid'), 39 | ), 40 | ); 41 | 42 | // Assert that getOrCrash returns the value for the valid object 43 | expect(valid.getOrCrash(), 'valid'); 44 | 45 | // Assert that getOrCrash throws an exception for the invalid object 46 | expect(invalid.getOrCrash, throwsA(isA())); 47 | }); 48 | 49 | // Define a test case for the getOrElse method 50 | test('getOrElse should return the value or a default value', () { 51 | // Create a valid and an invalid TestValueObject 52 | final valid = TestValueObject(right('valid')); 53 | final invalid = TestValueObject( 54 | left( 55 | const ValueFailure.empty(failedValue: 'invalid'), 56 | ), 57 | ); 58 | 59 | // Assert that getOrElse returns the value for the valid object 60 | expect(valid.getOrElse('default'), 'valid'); 61 | 62 | // Assert that getOrElse returns the default value for the invalid object 63 | expect(invalid.getOrElse('default'), 'default'); 64 | }); 65 | 66 | // Define a test case for the failureOrUnit property 67 | test('failureOrUnit should return the failure or unit', () { 68 | // Create a valid and an invalid TestValueObject 69 | final valid = TestValueObject(right('valid')); 70 | final invalid = TestValueObject( 71 | left( 72 | const ValueFailure.empty(failedValue: 'invalid'), 73 | ), 74 | ); 75 | 76 | // Assert that failureOrUnit returns unit for the valid object 77 | expect(valid.failureOrUnit, right, Unit>(unit)); 78 | 79 | // Assert that failureOrUnit returns the failure for the invalid object 80 | expect( 81 | invalid.failureOrUnit, 82 | left, Unit>( 83 | const ValueFailure.empty( 84 | failedValue: 'invalid', 85 | ), 86 | ), 87 | ); 88 | }); 89 | 90 | // Define a test case for the isValid method 91 | test('isValid should return true or false', () { 92 | // Create a valid and an invalid TestValueObject 93 | final valid = TestValueObject(right('valid')); 94 | final invalid = TestValueObject( 95 | left( 96 | const ValueFailure.empty(failedValue: 'invalid'), 97 | ), 98 | ); 99 | 100 | // Assert that isValid returns true for the valid object 101 | expect(valid.isValid(), true); 102 | 103 | // Assert that isValid returns false for the invalid object 104 | expect(invalid.isValid(), false); 105 | }); 106 | }); 107 | } 108 | -------------------------------------------------------------------------------- /test/core/domain/entities/value_validators_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_test/flutter_test.dart'; 2 | import 'package:template/core/domain/entities/value_validators.dart'; 3 | import 'package:template/core/domain/failures/value_failure.dart'; 4 | import 'package:template/core/extensions/dartz_extensions.dart'; 5 | 6 | void main() { 7 | group('Value Validator', () { 8 | group('Validate Single Line', () { 9 | test( 10 | 'should return failure when multiline text.', 11 | () async { 12 | // arrange 13 | const input = 'this is the first line \n and this is the second one.'; 14 | // act 15 | final validation = validateSingleLine(input); 16 | final output = validation.getRight(); 17 | final failure = validation.getLeft(); 18 | 19 | // assert 20 | expect(validation.isLeft(), isTrue); 21 | expect(output, isNull); 22 | expect(failure, isA>()); 23 | }, 24 | ); 25 | 26 | test( 27 | 'should return String when validated', 28 | () async { 29 | // arrange 30 | const input = 'this is only single line'; 31 | // act 32 | final validation = validateSingleLine(input); 33 | final output = validation.getRight(); 34 | final failure = validation.getLeft(); 35 | // assert 36 | expect(validation.isRight(), isTrue); 37 | expect(output, isA()); 38 | expect(output, equals(input)); 39 | expect(failure, isNull); 40 | }, 41 | ); 42 | }); 43 | 44 | group('Validate Unique Id', () { 45 | test( 46 | 'should return Value Failure when invalid UUID', 47 | () async { 48 | // arrange 49 | const input = '10492'; 50 | // act 51 | final validated = validateUniqueId(input); 52 | final output = validated.getRight(); 53 | final failure = validated.getLeft(); 54 | // assert 55 | expect(validated.isLeft(), isTrue); 56 | expect(failure, isA>()); 57 | expect(output, isNull); 58 | }, 59 | ); 60 | 61 | test( 62 | 'should return valid UUID String', 63 | () async { 64 | // arrange 65 | const input = 'f398a930-77b3-4395-be13-4bc5b53cb2f9'; 66 | // act 67 | final validated = validateUniqueId(input); 68 | final output = validated.getRight(); 69 | final failure = validated.getLeft(); 70 | // assert 71 | expect(validated.isRight(), isTrue); 72 | expect(output, isA()); 73 | expect(output, equals(input)); 74 | expect(failure, isNull); 75 | }, 76 | ); 77 | }); 78 | }); 79 | } 80 | -------------------------------------------------------------------------------- /test/core/domain/failures/errors_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_test/flutter_test.dart'; 2 | import 'package:template/core/domain/failures/errors.dart'; 3 | import 'package:template/core/domain/failures/value_failure.dart'; 4 | 5 | void main() { 6 | // Define a group of tests for the UnexpectedValueError class 7 | group('UnexpectedValueError', () { 8 | // Define a test case for the constructor and valueFailure property 9 | test('should have a valueFailure property', () { 10 | // Create a sample ValueFailure object 11 | const failure = ValueFailure.empty(failedValue: 'invalid'); 12 | 13 | // Create an UnexpectedValueError object with the sample failure 14 | final error = UnexpectedValueError(failure); 15 | 16 | // Assert that the error has the same failure as its valueFailure property 17 | expect(error.valueFailure, failure); 18 | }); 19 | 20 | // Define a test case for the toString method 21 | test('toString should return a descriptive message', () { 22 | // Create a sample ValueFailure object 23 | const failure = ValueFailure.empty(failedValue: 'invalid'); 24 | 25 | // Create an UnexpectedValueError object with the sample failure 26 | final error = UnexpectedValueError(failure); 27 | 28 | // Define the expected message 29 | const message = 30 | '"Encountered a ValueFailure at an unrecoverable point. Terminating. ' 31 | 'Failure was: ValueFailure.empty(failedValue: invalid)"'; 32 | 33 | // Assert that the error's toString method returns the expected message 34 | expect(error.toString(), equals(message)); 35 | }); 36 | }); 37 | } 38 | -------------------------------------------------------------------------------- /test/core/domain/failures/failure.codegen_test.dart: -------------------------------------------------------------------------------- 1 | // Import the test and freezed_test packages 2 | import 'package:flutter_test/flutter_test.dart'; 3 | import 'package:template/core/domain/failures/failure.dart'; 4 | 5 | void main() { 6 | // Define a group of tests for the Failure class 7 | group('Failure', () { 8 | // Define a test case for the localFailure constructor and message property 9 | test('localFailure should have a message property', () { 10 | // Create a sample localFailure object 11 | const failure = Failure.localFailure(message: 'Local failure'); 12 | 13 | // Assert that the failure is a localFailure with the given message 14 | expect( 15 | failure, 16 | equals( 17 | const Failure.localFailure(message: 'Local failure'), 18 | ), 19 | ); 20 | expect((failure as LocalFailure).message, 'Local failure'); 21 | }); 22 | 23 | // Define a test case for the serverFailure constructor and message property 24 | test('serverFailure should have a message property', () { 25 | // Create a sample serverFailure object 26 | const failure = Failure.serverFailure(message: 'Server failure'); 27 | 28 | // Assert that the failure is a serverFailure with the given message 29 | expect( 30 | failure, 31 | equals( 32 | const Failure.serverFailure(message: 'Server failure'), 33 | ), 34 | ); 35 | expect((failure as ServerFailure).message, 'Server failure'); 36 | }); 37 | }); 38 | } 39 | -------------------------------------------------------------------------------- /test/core/domain/failures/value_failure.codegen_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_test/flutter_test.dart'; 2 | import 'package:template/core/domain/failures/value_failure.dart'; 3 | 4 | void main() { 5 | // Define a group of tests for the ValueFailure class 6 | group('ValueFailure', () { 7 | // Define a test case for the empty constructor and failedValue property 8 | test('empty should have a failedValue property', () { 9 | // Create a sample empty object 10 | const failure = ValueFailure.empty(failedValue: ''); 11 | 12 | // Assert that the failure is an empty with the given failedValue 13 | expect(failure, equals(const ValueFailure.empty(failedValue: ''))); 14 | expect((failure as ValueFailureEmpty).failedValue, ''); 15 | }); 16 | 17 | // Define a test case for the multiLine constructor and failedValue property 18 | test('multiLine should have a failedValue property', () { 19 | // Create a sample multiLine object 20 | const failure = ValueFailure.multiLine(failedValue: 'foo\nbar'); 21 | 22 | // Assert that the failure is a multiLine with the given failedValue 23 | expect( 24 | failure, 25 | equals( 26 | const ValueFailure.multiLine(failedValue: 'foo\nbar'), 27 | ), 28 | ); 29 | expect((failure as ValueFailureMultiLine).failedValue, 'foo\nbar'); 30 | }); 31 | 32 | // Define a test case for the notInRange constructor and failedValue, 33 | //minimum, and maximum properties 34 | test('notInRange should have failedValue, minimum, and maximum properties', 35 | () { 36 | // Create a sample notInRange object 37 | const failure = ValueFailure.notInRange( 38 | failedValue: 0, 39 | minimum: 1, 40 | maximum: 10, 41 | ); 42 | 43 | // Assert that the failure is a notInRange with the given properties 44 | expect( 45 | failure, 46 | equals( 47 | const ValueFailure.notInRange( 48 | failedValue: 0, 49 | minimum: 1, 50 | maximum: 10, 51 | ), 52 | ), 53 | ); 54 | expect((failure as ValueFailureNotInRange).failedValue, 0); 55 | expect((failure as ValueFailureNotInRange).minimum, 1); 56 | expect((failure as ValueFailureNotInRange).maximum, 10); 57 | }); 58 | 59 | // Define a test case for the invalidUniqueId constructor 60 | //and failedValue property 61 | test('invalidUniqueId should have a failedValue property', () { 62 | // Create a sample invalidUniqueId object 63 | const failure = ValueFailure.invalidUniqueId(failedValue: '123'); 64 | 65 | // Assert that the failure is an invalidUniqueId 66 | //with the given failedValue 67 | expect( 68 | failure, 69 | equals( 70 | const ValueFailure.invalidUniqueId( 71 | failedValue: '123', 72 | ), 73 | ), 74 | ); 75 | expect((failure as ValueFailureInvalidUniqueId).failedValue, '123'); 76 | }); 77 | }); 78 | } 79 | -------------------------------------------------------------------------------- /test/core/domain/usecases/use_case_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:dartz/dartz.dart'; 2 | import 'package:flutter_test/flutter_test.dart'; 3 | import 'package:template/core/domain/failures/failure.dart'; 4 | import 'package:template/core/domain/usecases/use_case.dart'; 5 | 6 | class TestUseCase implements UseCase { 7 | @override 8 | Future> call(NoParams params) async { 9 | return right('Success'); 10 | } 11 | } 12 | 13 | // Define a sample stream use case class that implements StreamUseCase 14 | class TestStreamUseCase implements StreamUseCase { 15 | @override 16 | Stream> call(NoParams params) { 17 | return Stream.value(right('Success')); 18 | } 19 | } 20 | 21 | void main() { 22 | // Define a group of tests for the UseCase and StreamUseCase classes 23 | group('UseCase and StreamUseCase', () { 24 | // Define a sample use case class that implements UseCase 25 | 26 | // Define a test case for the UseCase interface 27 | test('should implement UseCase interface', () { 28 | // Create a sample TestUseCase object 29 | final useCase = TestUseCase(); 30 | 31 | // Assert that it implements UseCase interface 32 | expect(useCase, isA>()); 33 | }); 34 | 35 | // Define a test case for the StreamUseCase interface 36 | test('should implement StreamUseCase interface', () { 37 | // Create a sample TestStreamUseCase object 38 | final streamUseCase = TestStreamUseCase(); 39 | 40 | // Assert that it implements StreamUseCase interface 41 | expect(streamUseCase, isA>()); 42 | }); 43 | }); 44 | } 45 | -------------------------------------------------------------------------------- /test/core/extensions/context_extensions_test.dart: -------------------------------------------------------------------------------- 1 | // Import the necessary packages 2 | import 'package:bloc_test/bloc_test.dart'; 3 | import 'package:flutter/material.dart'; 4 | import 'package:flutter_bloc/flutter_bloc.dart'; 5 | import 'package:flutter_test/flutter_test.dart'; 6 | import 'package:mocktail/mocktail.dart'; 7 | import 'package:template/core/extensions/context_extensions.dart'; 8 | import 'package:template/shared/flash/presentation/blocs/cubit/flash_cubit.dart'; 9 | 10 | // Import the file that contains the extension 11 | 12 | // Create a mock class for the FlashCubit 13 | class MockFlashCubit extends MockCubit implements FlashCubit {} 14 | 15 | void main() { 16 | // Initialize the mock cubit and the scaffold messenger key 17 | late MockFlashCubit mockFlashCubit; 18 | 19 | setUp(() { 20 | // Create an instance of the mock cubit 21 | mockFlashCubit = MockFlashCubit(); 22 | // Register the fallback values for the mocktail library 23 | registerFallbackValue(const FlashState.disappeared()); 24 | when(() => mockFlashCubit.displayFlash('Hello')) 25 | .thenAnswer((invocation) async {}); 26 | }); 27 | 28 | // Test the displayFlash method 29 | testWidgets('displayFlash should call displayFlash on the cubit', 30 | (tester) async { 31 | // Arrange: create a test widget that uses the extension method 32 | final testWidget = MaterialApp( 33 | home: BlocProvider( 34 | create: (context) => mockFlashCubit, 35 | child: Builder( 36 | builder: (context) { 37 | return TextButton( 38 | onPressed: () { 39 | context.displayFlash('Hello'); 40 | }, 41 | child: const Text('Press me'), 42 | ); 43 | }, 44 | ), 45 | ), 46 | ); 47 | 48 | // Act: pump the test widget and tap on the button 49 | await tester.pumpWidget(testWidget); 50 | await tester.tap(find.byType(TextButton)); 51 | 52 | // Assert: verify that the displayFlash method was 53 | //called on the cubit with the correct message 54 | verify(() => mockFlashCubit.displayFlash('Hello')).called(1); 55 | }); 56 | } 57 | -------------------------------------------------------------------------------- /test/core/extensions/dartz_extensions_test.dart: -------------------------------------------------------------------------------- 1 | // Import the necessary packages 2 | import 'package:dartz/dartz.dart'; 3 | import 'package:flutter_test/flutter_test.dart'; 4 | import 'package:template/core/extensions/dartz_extensions.dart'; 5 | 6 | void main() { 7 | // Test the getRight method 8 | test('getRight should return the right value of an Either', () { 9 | // Arrange: create some Either values 10 | const either1 = Right(42); 11 | const either2 = Left('error'); 12 | 13 | // Act: call the getRight method on the Either values 14 | final result1 = either1.getRight(); 15 | final result2 = either2.getRight(); 16 | 17 | // Assert: expect the results to match the right values or null 18 | expect(result1, 42); 19 | expect(result2, null); 20 | }); 21 | 22 | // Test the getLeft method 23 | test('getLeft should return the left value of an Either', () { 24 | // Arrange: create some Either values 25 | const either1 = Right(42); 26 | const either2 = Left('error'); 27 | 28 | // Act: call the getLeft method on the Either values 29 | final result1 = either1.getLeft(); 30 | final result2 = either2.getLeft(); 31 | 32 | // Assert: expect the results to match the left values or null 33 | expect(result1, null); 34 | expect(result2, 'error'); 35 | }); 36 | 37 | // Test the unwrapRight method 38 | test('unwrapRight should return the right value of an Either or null', () { 39 | // Arrange: create some Either values 40 | const either1 = Right(42); 41 | const either2 = Left('error'); 42 | 43 | // Act: call the unwrapRight method on the Either values 44 | final result1 = either1.unwrapRight(); 45 | final result2 = either2.unwrapRight(); 46 | 47 | // Assert: expect the results to match the right values or null 48 | expect(result1, 42); 49 | expect(result2, null); 50 | }); 51 | } 52 | -------------------------------------------------------------------------------- /test/features/counter/data/datasources/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/test/features/counter/data/datasources/.gitkeep -------------------------------------------------------------------------------- /test/features/counter/data/models/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/test/features/counter/data/models/.gitkeep -------------------------------------------------------------------------------- /test/features/counter/data/repositories/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/test/features/counter/data/repositories/.gitkeep -------------------------------------------------------------------------------- /test/features/counter/domain/entities/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/test/features/counter/domain/entities/.gitkeep -------------------------------------------------------------------------------- /test/features/counter/domain/repositories/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/test/features/counter/domain/repositories/.gitkeep -------------------------------------------------------------------------------- /test/features/counter/domain/usecases/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/test/features/counter/domain/usecases/.gitkeep -------------------------------------------------------------------------------- /test/features/counter/presentation/blocs/counter_cubit_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, Adryan Eka Vandra 2 | // https://github.com/adryanev/flutter-template-architecture-template 3 | // 4 | // Use of this source code is governed by an MIT-style 5 | // license that can be found in the LICENSE file or at 6 | // https://opensource.org/licenses/MIT. 7 | 8 | import 'package:bloc_test/bloc_test.dart'; 9 | import 'package:flutter_test/flutter_test.dart'; 10 | import 'package:template/features/counter/counter.dart'; 11 | 12 | void main() { 13 | group('CounterCubit', () { 14 | test('initial state is 0', () { 15 | expect(CounterCubit().state, equals(0)); 16 | }); 17 | 18 | blocTest( 19 | 'emits [1] when increment is called', 20 | build: CounterCubit.new, 21 | act: (cubit) => cubit.increment(), 22 | expect: () => [equals(1)], 23 | ); 24 | 25 | blocTest( 26 | 'emits [-1] when decrement is called', 27 | build: CounterCubit.new, 28 | act: (cubit) => cubit.decrement(), 29 | expect: () => [equals(-1)], 30 | ); 31 | }); 32 | } 33 | -------------------------------------------------------------------------------- /test/features/counter/presentation/pages/counter_page_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, Adryan Eka Vandra 2 | // https://github.com/adryanev/flutter-template-architecture-template 3 | // 4 | // Use of this source code is governed by an MIT-style 5 | // license that can be found in the LICENSE file or at 6 | // https://opensource.org/licenses/MIT. 7 | 8 | import 'package:bloc_test/bloc_test.dart'; 9 | import 'package:flutter/material.dart'; 10 | import 'package:flutter_bloc/flutter_bloc.dart'; 11 | import 'package:flutter_test/flutter_test.dart'; 12 | import 'package:mocktail/mocktail.dart'; 13 | import 'package:template/features/counter/counter.dart'; 14 | 15 | import '../../../../helpers/helpers.dart'; 16 | 17 | class MockCounterCubit extends MockCubit implements CounterCubit {} 18 | 19 | void main() { 20 | group('CounterPage', () { 21 | testWidgets('renders CounterView', (tester) async { 22 | await tester.pumpApp(const CounterPage()); 23 | expect(find.byType(CounterView), findsOneWidget); 24 | }); 25 | }); 26 | 27 | group('CounterView', () { 28 | late CounterCubit counterCubit; 29 | 30 | setUp(() { 31 | counterCubit = MockCounterCubit(); 32 | }); 33 | 34 | testWidgets('renders current count', (tester) async { 35 | const state = 42; 36 | when(() => counterCubit.state).thenReturn(state); 37 | await tester.pumpApp( 38 | BlocProvider.value( 39 | value: counterCubit, 40 | child: const CounterView(), 41 | ), 42 | ); 43 | expect(find.text('$state'), findsOneWidget); 44 | }); 45 | 46 | testWidgets('calls increment when increment button is tapped', 47 | (tester) async { 48 | when(() => counterCubit.state).thenReturn(0); 49 | when(() => counterCubit.increment()).thenReturn(null); 50 | await tester.pumpApp( 51 | BlocProvider.value( 52 | value: counterCubit, 53 | child: const CounterView(), 54 | ), 55 | ); 56 | await tester.tap(find.byIcon(Icons.add)); 57 | verify(() => counterCubit.increment()).called(1); 58 | }); 59 | 60 | testWidgets('calls decrement when decrement button is tapped', 61 | (tester) async { 62 | when(() => counterCubit.state).thenReturn(0); 63 | when(() => counterCubit.decrement()).thenReturn(null); 64 | await tester.pumpApp( 65 | BlocProvider.value( 66 | value: counterCubit, 67 | child: const CounterView(), 68 | ), 69 | ); 70 | await tester.tap(find.byIcon(Icons.remove)); 71 | verify(() => counterCubit.decrement()).called(1); 72 | }); 73 | }); 74 | } 75 | -------------------------------------------------------------------------------- /test/features/counter/presentation/widgets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adryanev/flutter-mobile-clean-architecture-template/70d960e0a2732fe9e37182b4e2b1944ed5abfd2e/test/features/counter/presentation/widgets/.gitkeep -------------------------------------------------------------------------------- /test/fixtures/fixture_reader.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io'; 2 | 3 | /// Read fixture data as string 4 | /// Example: 5 | /// ```dart 6 | /// final data = fixture('user','user.json'); 7 | /// ``` 8 | /// Where `user` is a [path] is folder inside fixture, 9 | /// and `user.json` is the file [name]. 10 | String fixture(String path, String name) => 11 | File('$path/$name').readAsStringSync(); 12 | -------------------------------------------------------------------------------- /test/fixtures/user/user.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Hello", 3 | "occupation": "World" 4 | } 5 | -------------------------------------------------------------------------------- /test/helpers/configure_injector.dart: -------------------------------------------------------------------------------- 1 | import 'package:template/core/utils/constants.dart'; 2 | import 'package:template/injector.dart'; 3 | 4 | Future configureInjector() async { 5 | await configureDependencies(environment: Environment.test); 6 | } 7 | -------------------------------------------------------------------------------- /test/helpers/helpers.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, Adryan Eka Vandra 2 | // https://github.com/adryanev/flutter-template-architecture-template 3 | // 4 | // Use of this source code is governed by an MIT-style 5 | // license that can be found in the LICENSE file or at 6 | // https://opensource.org/licenses/MIT. 7 | 8 | export 'configure_injector.dart'; 9 | export 'pump_app.dart'; 10 | -------------------------------------------------------------------------------- /test/helpers/pump_app.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, Adryan Eka Vandra 2 | // https://github.com/adryanev/flutter-template-architecture-template 3 | // 4 | // Use of this source code is governed by an MIT-style 5 | // license that can be found in the LICENSE file or at 6 | // https://opensource.org/licenses/MIT. 7 | 8 | import 'package:flutter/material.dart'; 9 | import 'package:flutter_localizations/flutter_localizations.dart'; 10 | import 'package:flutter_test/flutter_test.dart'; 11 | import 'package:template/app/router/app_router.dart'; 12 | import 'package:template/l10n/l10n.dart'; 13 | 14 | extension PumpApp on WidgetTester { 15 | Future pumpApp(Widget widget) { 16 | return pumpWidget( 17 | MaterialApp( 18 | localizationsDelegates: const [ 19 | AppLocalizations.delegate, 20 | GlobalMaterialLocalizations.delegate, 21 | ], 22 | supportedLocales: AppLocalizations.supportedLocales, 23 | home: widget, 24 | ), 25 | ); 26 | } 27 | 28 | Future pumpAppRouter( 29 | String location, 30 | Widget Function(Widget child) builder, { 31 | bool isConnected = true, 32 | }) { 33 | return pumpWidget( 34 | MaterialApp.router( 35 | localizationsDelegates: const [ 36 | AppLocalizations.delegate, 37 | GlobalMaterialLocalizations.delegate, 38 | ], 39 | supportedLocales: AppLocalizations.supportedLocales, 40 | routeInformationProvider: router(location).routeInformationProvider, 41 | routeInformationParser: router(location).routeInformationParser, 42 | routerDelegate: router(location).routerDelegate, 43 | ), 44 | ); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /test/shared/domain/entities/value_objects_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_test/flutter_test.dart'; 2 | import 'package:template/core/domain/failures/value_failure.dart'; 3 | import 'package:template/core/extensions/dartz_extensions.dart'; 4 | import 'package:template/shared/domain/entities/value_objects.dart'; 5 | 6 | void main() { 7 | group('StringSingleLine', () { 8 | test( 9 | 'should contains ValueFailure when inputted with multi line string', 10 | () async { 11 | // arrange 12 | const input = 'this is \n multi line text'; 13 | // act 14 | final singleLine = StringSingleLine(input); 15 | final output = singleLine.value.getRight(); 16 | final failure = singleLine.value.getLeft(); 17 | 18 | // assert 19 | expect(singleLine.isValid(), isFalse); 20 | expect(output, isNull); 21 | expect(failure, isA>()); 22 | }, 23 | ); 24 | 25 | test( 26 | 'should contains String when valid ', 27 | () async { 28 | // arrange 29 | const input = 'this is single line'; 30 | // act 31 | final singleLine = StringSingleLine(input); 32 | final output = singleLine.value.getRight(); 33 | final failure = singleLine.value.getLeft(); 34 | // assert 35 | expect(singleLine.isValid(), isTrue); 36 | expect(output, isA()); 37 | expect(output, equals(input)); 38 | expect(failure, isNull); 39 | }, 40 | ); 41 | }); 42 | group('UniqueId', () { 43 | test( 44 | 'should contains ValueInvalidUniqueId when accepting invalid UUID', 45 | () async { 46 | // arrange 47 | const input = 'not a valid uuid'; 48 | // act 49 | final uniqueId = UniqueId(input); 50 | final output = uniqueId.value.getRight(); 51 | final failure = uniqueId.value.getLeft(); 52 | // assert 53 | expect(uniqueId, isA()); 54 | expect(uniqueId.isValid(), isFalse); 55 | expect(output, isNull); 56 | expect(failure, isA>()); 57 | }, 58 | ); 59 | 60 | test( 61 | 'should contains Valid UUID when accepting valid UUID', 62 | () async { 63 | // arrange 64 | const input = 'f398a930-77b3-4395-be13-4bc5b53cb2f9'; 65 | // act 66 | final uniqueId = UniqueId(input); 67 | final output = uniqueId.value.getRight(); 68 | final failure = uniqueId.value.getLeft(); 69 | 70 | // assert 71 | expect(uniqueId, isA()); 72 | expect(uniqueId.isValid(), isTrue); 73 | expect(failure, isNull); 74 | expect(output, isA()); 75 | expect(output, equals(input)); 76 | }, 77 | ); 78 | 79 | test( 80 | 'should generate valid UUID', 81 | () async { 82 | // arrange 83 | 84 | // act 85 | final uniqueId = UniqueId.generate(); 86 | final output = uniqueId.value.getRight(); 87 | final failure = uniqueId.value.getLeft(); 88 | 89 | // assert 90 | expect(uniqueId, isA()); 91 | expect(uniqueId.isValid(), isTrue); 92 | expect(failure, isNull); 93 | expect(output, isA()); 94 | }, 95 | ); 96 | }); 97 | } 98 | -------------------------------------------------------------------------------- /test/shared/domain/formz/email_input_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_test/flutter_test.dart'; 2 | import 'package:template/shared/domain/formz/email_input.dart'; 3 | 4 | void main() { 5 | group('EmailInput Pure', () { 6 | test( 7 | 'should return status pure and invalid when initiated without value', 8 | () async { 9 | // act 10 | const form = EmailInput.pure(); 11 | // assert 12 | expect(form.isPure, isTrue); 13 | }, 14 | ); 15 | 16 | test( 17 | 'should return status pure and valid when initiated with value', 18 | () async { 19 | // arrange 20 | const oldEmail = 'test@example.com'; 21 | // act 22 | const form = EmailInput.pure(oldEmail); 23 | // assert 24 | expect(form.isPure, isTrue); 25 | expect(form.value, equals(oldEmail)); 26 | expect(form.isValid, isTrue); 27 | expect(form.error, isNull); 28 | expect(form.isNotValid, isFalse); 29 | }, 30 | ); 31 | }); 32 | 33 | group('EmailInput Dirty', () { 34 | test( 35 | 'should return status dirty and invalid when initiated without value', 36 | () async { 37 | // act 38 | const form = EmailInput.dirty(); 39 | // assert 40 | expect(form.isPure, isFalse); 41 | expect(form.isValid, isFalse); 42 | expect(form.displayError, equals(EmailValidationError.invalid)); 43 | }, 44 | ); 45 | 46 | test( 47 | 'should return status dirty and valid when initiated with value', 48 | () async { 49 | // arrange 50 | const oldEmail = 'test@example.com'; 51 | // act 52 | const form = EmailInput.dirty(oldEmail); 53 | // assert 54 | expect(form.isPure, isFalse); 55 | expect(form.value, equals(oldEmail)); 56 | expect(form.isValid, isTrue); 57 | expect(form.error, isNull); 58 | expect(form.isNotValid, isFalse); 59 | }, 60 | ); 61 | }); 62 | } 63 | -------------------------------------------------------------------------------- /test/shared/domain/formz/password_confirmation_input_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_test/flutter_test.dart'; 2 | import 'package:template/shared/domain/formz/password_confirmation_input.dart'; 3 | 4 | void main() { 5 | group('PasswordConfirmationInput Pure', () { 6 | test( 7 | 'should return status pure and invalid when initiated without value', 8 | () async { 9 | // act 10 | const form = PasswordConfirmationInput.pure(); 11 | // assert 12 | expect(form.isPure, isTrue); 13 | }, 14 | ); 15 | 16 | test( 17 | 'should return status pure and valid when initiated with value', 18 | () async { 19 | // arrange 20 | const oldPassword = 'Asdf1234'; 21 | // act 22 | const form = PasswordConfirmationInput.pure(oldPassword); 23 | // assert 24 | expect(form.isPure, isTrue); 25 | expect(form.value, equals(oldPassword)); 26 | expect(form.isValid, isFalse); 27 | expect( 28 | form.error, 29 | equals(PasswordConfirmationValidationError.mismatch), 30 | ); 31 | expect(form.isNotValid, isTrue); 32 | }, 33 | ); 34 | }); 35 | 36 | group('PasswordConfirmationInput Dirty', () { 37 | test( 38 | 'should return status dirty and invalid when initiated without value', 39 | () async { 40 | //arrange 41 | const oldPassword = 'Asdf1234'; 42 | // act 43 | const form = PasswordConfirmationInput.dirty(oldPassword); 44 | // assert 45 | expect(form.isPure, isFalse); 46 | expect(form.isValid, isFalse); 47 | expect( 48 | form.displayError, 49 | equals( 50 | PasswordConfirmationValidationError.mismatch, 51 | ), 52 | ); 53 | }, 54 | ); 55 | 56 | test( 57 | 'should return status dirty and not valid when mismatch', 58 | () async { 59 | // arrange 60 | const oldPassword = 'Asdf1234'; 61 | const newPassword = 'Asdf1345'; 62 | // act 63 | const form = PasswordConfirmationInput.dirty(oldPassword, newPassword); 64 | // assert 65 | expect(form.isPure, isFalse); 66 | expect(form.value, equals(newPassword)); 67 | expect(form.isValid, isFalse); 68 | expect( 69 | form.error, 70 | equals(PasswordConfirmationValidationError.mismatch), 71 | ); 72 | expect(form.isNotValid, isTrue); 73 | }, 74 | ); 75 | test( 76 | 'should return status dirty and valid when initiated with value', 77 | () async { 78 | // arrange 79 | const oldPassword = 'Asdf1234'; 80 | const newPassword = 'Asdf1234'; 81 | // act 82 | const form = PasswordConfirmationInput.dirty(oldPassword, newPassword); 83 | // assert 84 | expect(form.isPure, isFalse); 85 | expect(form.value, equals(newPassword)); 86 | expect(form.isValid, isTrue); 87 | expect(form.error, isNull); 88 | expect(form.isNotValid, isFalse); 89 | }, 90 | ); 91 | }); 92 | } 93 | -------------------------------------------------------------------------------- /test/shared/domain/formz/password_input_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_test/flutter_test.dart'; 2 | import 'package:template/shared/domain/formz/password_input.dart'; 3 | 4 | void main() { 5 | group('PasswordInput Pure', () { 6 | test( 7 | 'should return status pure and invalid when initiated without value', 8 | () async { 9 | // act 10 | const form = PasswordInput.pure(); 11 | // assert 12 | expect(form.isPure, isTrue); 13 | }, 14 | ); 15 | 16 | test( 17 | 'should return status pure and valid when initiated with value', 18 | () async { 19 | // arrange 20 | const oldPassword = 'Asdf1234'; 21 | // act 22 | const form = PasswordInput.pure(oldPassword); 23 | // assert 24 | expect(form.isPure, isTrue); 25 | expect(form.value, equals(oldPassword)); 26 | expect(form.isValid, isTrue); 27 | expect(form.error, isNull); 28 | expect(form.isNotValid, isFalse); 29 | }, 30 | ); 31 | }); 32 | 33 | group('PasswordInput Dirty', () { 34 | test( 35 | 'should return status dirty and invalid when initiated without value', 36 | () async { 37 | // act 38 | const form = PasswordInput.dirty(); 39 | // assert 40 | expect(form.isPure, isFalse); 41 | expect(form.isValid, isFalse); 42 | expect(form.displayError, equals(PasswordValidationError.invalid)); 43 | }, 44 | ); 45 | 46 | test( 47 | 'should return status dirty and valid when initiated with value', 48 | () async { 49 | // arrange 50 | const oldPassword = 'Asdf1234'; 51 | // act 52 | const form = PasswordInput.dirty(oldPassword); 53 | // assert 54 | expect(form.isPure, isFalse); 55 | expect(form.value, equals(oldPassword)); 56 | expect(form.isValid, isTrue); 57 | expect(form.error, isNull); 58 | expect(form.isNotValid, isFalse); 59 | }, 60 | ); 61 | }); 62 | } 63 | --------------------------------------------------------------------------------