├── .flutter-plugins
├── .flutter-plugins-dependencies
├── .fvm
├── flutter_sdk
└── fvm_config.json
├── .gitignore
├── .idea
├── libraries
│ ├── Dart_SDK.xml
│ └── KotlinJavaRuntime.xml
├── modules.xml
├── runConfigurations
│ └── main_dart.xml
└── workspace.xml
├── .metadata
├── .vscode
└── launch.json
├── README.md
├── analysis_options.yaml
├── android
├── .gitignore
├── app
│ ├── build.gradle
│ └── src
│ │ ├── debug
│ │ └── AndroidManifest.xml
│ │ ├── main
│ │ ├── AndroidManifest.xml
│ │ ├── kotlin
│ │ │ └── com
│ │ │ │ └── example
│ │ │ │ └── clean_code_architecture_flutter
│ │ │ │ └── MainActivity.kt
│ │ └── res
│ │ │ ├── drawable
│ │ │ └── launch_background.xml
│ │ │ ├── mipmap-hdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-mdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ └── ic_launcher.png
│ │ │ └── values
│ │ │ └── styles.xml
│ │ └── profile
│ │ └── AndroidManifest.xml
├── build.gradle
├── clean_code_architecture_flutter_android.iml
├── gradle.properties
├── gradle
│ └── wrapper
│ │ └── gradle-wrapper.properties
└── settings.gradle
├── build.yaml
├── ios
├── .gitignore
├── Flutter
│ ├── .last_build_id
│ ├── AppFrameworkInfo.plist
│ ├── Debug.xcconfig
│ └── Release.xcconfig
├── Podfile
├── Podfile.lock
├── Runner.xcodeproj
│ ├── project.pbxproj
│ ├── project.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ │ ├── IDEWorkspaceChecks.plist
│ │ │ └── WorkspaceSettings.xcsettings
│ └── xcshareddata
│ │ └── xcschemes
│ │ └── Runner.xcscheme
├── Runner.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ ├── IDEWorkspaceChecks.plist
│ │ └── WorkspaceSettings.xcsettings
└── Runner
│ ├── AppDelegate.swift
│ ├── Assets.xcassets
│ ├── AppIcon.appiconset
│ │ ├── Contents.json
│ │ ├── Icon-App-1024x1024@1x.png
│ │ ├── Icon-App-20x20@1x.png
│ │ ├── Icon-App-20x20@2x.png
│ │ ├── Icon-App-20x20@3x.png
│ │ ├── Icon-App-29x29@1x.png
│ │ ├── Icon-App-29x29@2x.png
│ │ ├── Icon-App-29x29@3x.png
│ │ ├── Icon-App-40x40@1x.png
│ │ ├── Icon-App-40x40@2x.png
│ │ ├── Icon-App-40x40@3x.png
│ │ ├── Icon-App-60x60@2x.png
│ │ ├── Icon-App-60x60@3x.png
│ │ ├── Icon-App-76x76@1x.png
│ │ ├── Icon-App-76x76@2x.png
│ │ └── Icon-App-83.5x83.5@2x.png
│ └── LaunchImage.imageset
│ │ ├── Contents.json
│ │ ├── LaunchImage.png
│ │ ├── LaunchImage@2x.png
│ │ ├── LaunchImage@3x.png
│ │ └── README.md
│ ├── Base.lproj
│ ├── LaunchScreen.storyboard
│ └── Main.storyboard
│ ├── Info.plist
│ └── Runner-Bridging-Header.h
├── lib
├── common
│ ├── configs
│ │ └── configuration.dart
│ ├── constants
│ │ ├── exception_constants.dart
│ │ ├── http_constants.dart
│ │ ├── local_database_type_constants.dart
│ │ └── route_constants.dart
│ ├── exceptions
│ │ ├── bad_request_exception.dart
│ │ ├── forbidden_exception.dart
│ │ ├── server_error_exception.dart
│ │ ├── server_exception.dart
│ │ └── unauthorized_exception.dart
│ ├── extensions
│ │ └── string_extension.dart
│ ├── http
│ │ └── http_client.dart
│ ├── injector
│ │ ├── injector.dart
│ │ ├── injector_config.dart
│ │ └── injector_config.g.dart
│ └── utils
│ │ ├── database_util.dart
│ │ └── http_utils.dart
├── data
│ ├── datasources
│ │ ├── local
│ │ │ └── local_database
│ │ │ │ ├── base_local_database.dart
│ │ │ │ ├── tables
│ │ │ │ ├── todo_table.dart
│ │ │ │ └── todo_table.g.dart
│ │ │ │ └── todo_local_datasource.dart
│ │ └── remote
│ │ │ ├── constants
│ │ │ └── todo_remote_datasource_constants.dart
│ │ │ └── todo_remote_datasource.dart
│ ├── models
│ │ └── todo_model.dart
│ └── repositories
│ │ └── todo_repository_impl.dart
├── domain
│ ├── entities
│ │ └── todo_entity.dart
│ ├── repositories
│ │ └── todo_repository.dart
│ └── usescases
│ │ └── todo_usecase.dart
├── main.dart
└── presentation
│ ├── app.dart
│ ├── journey
│ ├── dashboard
│ │ ├── dashboard_constants.dart
│ │ ├── dashboard_routes.dart
│ │ └── dashboard_screen.dart
│ └── todo
│ │ ├── bloc
│ │ ├── todo_bloc.dart
│ │ ├── todo_event.dart
│ │ └── todo_state.dart
│ │ ├── create_todo
│ │ ├── create_todo_constants.dart
│ │ └── create_todo_screen.dart
│ │ ├── todo_list
│ │ ├── todo_list_screen.dart
│ │ └── widgets
│ │ │ ├── todo_item.dart
│ │ │ └── todo_list_constants.dart
│ │ └── todo_routes.dart
│ ├── routes.dart
│ └── themes
│ ├── custom_icons.dart
│ ├── theme_colors.dart
│ ├── theme_data.dart
│ └── theme_text.dart
├── pubspec.yaml
└── test
├── __setup__
├── base_test_bloc.dart
├── navigation_mock.dart
├── path_provider_mock.dart
└── wrapper.dart
├── common
├── exceptions
│ ├── bad_request_exception_test.dart
│ ├── forbidden_exception_test.dart
│ ├── server_error_exception_test.dart
│ └── unauthorized_exception_test.dart
├── http
│ ├── __mock__
│ │ ├── http_client_data.dart
│ │ └── http_client_mock.dart
│ └── http_client_test.dart
└── utils
│ ├── __mock__
│ ├── sample_adapter.dart
│ ├── sample_table.dart
│ └── sample_table_mock.dart
│ ├── database_utils_test.dart
│ └── http_util_test.dart
├── data
├── datasources
│ ├── local
│ │ ├── __mock__
│ │ │ ├── base_local_datasource_mock.dart
│ │ │ ├── sample_model.dart
│ │ │ ├── todo_local_datasource_mock.dart
│ │ │ └── todo_table_data.dart
│ │ ├── base_local_datasource_test.dart
│ │ └── todo_local_datasource_test.dart
│ └── remote
│ │ ├── __mock__
│ │ ├── http_client_mock.dart
│ │ └── todo_remote_datasource_mock.dart
│ │ └── todo_remote_datasource_test.dart
├── models
│ ├── __mock__
│ │ └── todo_model_data.dart
│ └── todo_model_test.dart
└── repositories
│ ├── __mock__
│ ├── todo_json_data.dart
│ └── todo_repository_mock.dart
│ └── todo_repository_impl_test.dart
├── domain
├── entities
│ └── __mock__
│ │ └── todo_entity_data.dart
└── usecases
│ ├── __mock__
│ └── todo_usecase_mock.dart
│ └── todo_usecase_test.dart
├── local_database_test_files
├── database_util_test.hive
├── database_util_test.lock
├── testbox.hive
├── testbox.lock
├── todo.hive
└── todo.lock
└── presentation
├── app_test.dart
└── journey
├── dashboard
└── dashboard_screen_test.dart
└── todo
├── bloc
├── __mock__
│ └── todo_bloc_mock.dart
└── todo_bloc_test.dart
├── create_todo
└── create_todo_screen_test.dart
├── todo_list
├── todo_list_screen_test.dart
└── widgets
│ └── todo_item_test.dart
└── todo_routes_test.dart
/.flutter-plugins:
--------------------------------------------------------------------------------
1 | # This is a generated file; do not edit or check into version control.
2 | path_provider=/Users/rashmi/.pub-cache/hosted/pub.dartlang.org/path_provider-1.6.28/
3 | path_provider_linux=/Users/rashmi/.pub-cache/hosted/pub.dartlang.org/path_provider_linux-0.0.1+2/
4 | path_provider_macos=/Users/rashmi/.pub-cache/hosted/pub.dartlang.org/path_provider_macos-0.0.4+8/
5 | path_provider_windows=/Users/rashmi/.pub-cache/hosted/pub.dartlang.org/path_provider_windows-0.0.4+3/
6 |
--------------------------------------------------------------------------------
/.flutter-plugins-dependencies:
--------------------------------------------------------------------------------
1 | {"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"path_provider","path":"/Users/rashmi/.pub-cache/hosted/pub.dartlang.org/path_provider-1.6.28/","dependencies":[]}],"android":[{"name":"path_provider","path":"/Users/rashmi/.pub-cache/hosted/pub.dartlang.org/path_provider-1.6.28/","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"/Users/rashmi/.pub-cache/hosted/pub.dartlang.org/path_provider_macos-0.0.4+8/","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"/Users/rashmi/.pub-cache/hosted/pub.dartlang.org/path_provider_linux-0.0.1+2/","dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"/Users/rashmi/.pub-cache/hosted/pub.dartlang.org/path_provider_windows-0.0.4+3/","dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"path_provider","dependencies":["path_provider_macos","path_provider_linux","path_provider_windows"]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"path_provider_windows","dependencies":[]}],"date_created":"2021-04-06 01:59:15.644330","version":"1.22.5"}
--------------------------------------------------------------------------------
/.fvm/flutter_sdk:
--------------------------------------------------------------------------------
1 | /Users/rashmi/fvm/versions/1.22.5
--------------------------------------------------------------------------------
/.fvm/fvm_config.json:
--------------------------------------------------------------------------------
1 | {"flutterSdkVersion":"1.22.5"}
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://www.dartlang.org/guides/libraries/private-files
2 |
3 | # Files and directories created by pub
4 | .dart_tool/
5 | .packages
6 | build/
7 | # If you're building an application, you may want to check-in your pubspec.lock
8 | pubspec.lock
9 |
10 | # Directory created by dartdoc
11 | # If you don't generate documentation locally you can remove this line.
12 | doc/api/
13 |
14 | # Avoid committing generated Javascript files:
15 | *.dart.js
16 | *.info.json # Produced by the --dump-info flag.
17 | *.js # When generated by dart2js. Don't specify *.js if your
18 | # project includes source files written in JavaScript.
19 | *.js_
20 | *.js.deps
21 | *.js.map
22 |
--------------------------------------------------------------------------------
/.idea/libraries/Dart_SDK.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/.idea/libraries/KotlinJavaRuntime.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/.idea/runConfigurations/main_dart.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/workspace.xml:
--------------------------------------------------------------------------------
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 |
--------------------------------------------------------------------------------
/.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: 78910062997c3a836feee883712c241a5fd22983
8 | channel: unknown
9 |
10 | project_type: app
11 |
--------------------------------------------------------------------------------
/.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": "clean_code_architecture_flutter",
9 | "request": "launch",
10 | "type": "dart",
11 | "flutterMode": "debug",
12 | }
13 | ]
14 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # clean-code-architecture-flutter
2 |
3 | Seed app with clean code architecture
4 |
5 | In clean code architecture, there are three main layers
6 |
7 | - Data
8 | - Domain
9 | - Presentation
10 | along with
11 | - common (can also be called as core)
12 |
13 | 
14 |
15 | ## Common
16 |
17 | This contains all the common functionalities for the application.
18 | e.g http client, env config, platform specific stuffs like network checker, etc.
19 |
20 | These common functionalities will be used by data layer, domain layer and presentation layer
21 | e.g http client by remote data source, network info by repository layer, enums by
22 | domain layer and config by presentation.
23 |
24 | ## Domain
25 |
26 | This is innermost layer and will contain the core business logic i.e. usecases and business object also called as entities, the usecase depends on the contract of repository (not implementation)
27 |
28 | ## Data
29 |
30 | The data layers contains the repository implementation and this layer is closest to actual data sources and is responsible for communication with data sources.
31 |
32 | The data layer returns the models and not entities and the model also contains the fromJson and toJson mapper.
33 |
34 | Note: We don’t have an extra mapper class, we are just going to leverage the named constructor by dart to map our data set from one form to our models. toJson and fromJson.
35 |
36 | ## Presentation
37 |
38 | This layer contains all the information about the UI and everything to show to the end user customer. The presentation layer also contains the bloc which is the state management and often termed as brain of UI.
39 |
40 | The presentation layer interact via domain layer, i.e entities and use cases.
41 |
42 | # Folder structure
43 |
44 | ```
45 | ├── lib
46 | │ ├── common
47 | │ │ ├── configs
48 | │ │ │ └── configuration.dart
49 | │ │ ├── constants
50 | │ │ │ ├── exception_constants.dart
51 | │ │ │ ├── http_constants.dart
52 | │ │ │ ├── local_database_type_constants.dart
53 | │ │ │ └── route_constants.dart
54 | │ │ ├── exceptions
55 | │ │ │ ├── bad_request_exception.dart
56 | │ │ │ ├── forbidden_exception.dart
57 | │ │ │ ├── server_error_exception.dart
58 | │ │ │ ├── server_exception.dart
59 | │ │ │ └── unauthorized_exception.dart
60 | │ │ ├── extensions
61 | │ │ │ └── string_extension.dart
62 | │ │ ├── http
63 | │ │ │ └── http_client.dart
64 | │ │ ├── injector
65 | │ │ │ ├── injector.dart
66 | │ │ │ ├── injector_config.dart
67 | │ │ │ └── injector_config.g.dart
68 | │ │ └── utils
69 | │ │ ├── database_util.dart
70 | │ │ └── http_utils.dart
71 | │ ├── data
72 | │ │ ├── datasources
73 | │ │ │ ├── local
74 | │ │ │ │ ├── local_database
75 | │ │ │ │ │ ├── base_local_database.dart
76 | │ │ │ │ │ ├── tables
77 | │ │ │ │ │ │ ├── todo_table.dart
78 | │ │ │ │ │ │ └── todo_table.g.dart
79 | │ │ │ │ │ └── todo_local_datasource.dart
80 | │ │ │ │ └── shared_preference
81 | │ │ │ └── remote
82 | │ │ │ ├── constants
83 | │ │ │ │ └── todo_remote_datasource_constants.dart
84 | │ │ │ └── todo_remote_datasource.dart
85 | │ │ ├── models
86 | │ │ │ └── todo_model.dart
87 | │ │ └── repositories
88 | │ │ └── todo_repository_impl.dart
89 | │ ├── domain
90 | │ │ ├── entities
91 | │ │ │ └── todo_entity.dart
92 | │ │ ├── repositories
93 | │ │ │ └── todo_repository.dart
94 | │ │ └── usescases
95 | │ │ └── todo_usecase.dart
96 | │ ├── main.dart
97 | │ └── presentation
98 | │ ├── app.dart
99 | │ ├── common_bloc
100 | │ ├── journey
101 | │ │ ├── dashboard
102 | │ │ │ ├── dashboard_constants.dart
103 | │ │ │ ├── dashboard_routes.dart
104 | │ │ │ └── dashboard_screen.dart
105 | │ │ └── todo
106 | │ │ ├── bloc
107 | │ │ │ ├── todo_bloc.dart
108 | │ │ │ ├── todo_event.dart
109 | │ │ │ └── todo_state.dart
110 | │ │ ├── create_todo
111 | │ │ │ ├── create_todo_constants.dart
112 | │ │ │ └── create_todo_screen.dart
113 | │ │ ├── todo_list
114 | │ │ │ ├── todo_list_screen.dart
115 | │ │ │ └── widgets
116 | │ │ │ ├── todo_item.dart
117 | │ │ │ └── todo_list_constants.dart
118 | │ │ └── todo_routes.dart
119 | │ ├── routes.dart
120 | │ ├── themes
121 | │ │ ├── custom_icons.dart
122 | │ │ ├── theme_colors.dart
123 | │ │ ├── theme_data.dart
124 | │ │ └── theme_text.dart
125 | │ └── widgets
126 | ├── pubspec.lock
127 | ├── pubspec.yaml
128 | └── test
129 | ├── __setup__
130 | │ ├── base_test_bloc.dart
131 | │ ├── navigation_mock.dart
132 | │ ├── path_provider_mock.dart
133 | │ └── wrapper.dart
134 | ├── common
135 | │ ├── exceptions
136 | │ │ ├── bad_request_exception_test.dart
137 | │ │ ├── forbidden_exception_test.dart
138 | │ │ ├── server_error_exception_test.dart
139 | │ │ └── unauthorized_exception_test.dart
140 | │ ├── http
141 | │ │ ├── __mock__
142 | │ │ │ ├── http_client_data.dart
143 | │ │ │ └── http_client_mock.dart
144 | │ │ └── http_client_test.dart
145 | │ └── utils
146 | │ ├── __mock__
147 | │ │ ├── sample_adapter.dart
148 | │ │ ├── sample_table.dart
149 | │ │ └── sample_table_mock.dart
150 | │ ├── database_utils_test.dart
151 | │ └── http_util_test.dart
152 | ├── data
153 | │ ├── datasources
154 | │ │ ├── local
155 | │ │ │ ├── __mock__
156 | │ │ │ │ ├── base_local_datasource_mock.dart
157 | │ │ │ │ ├── sample_model.dart
158 | │ │ │ │ ├── todo_local_datasource_mock.dart
159 | │ │ │ │ └── todo_table_data.dart
160 | │ │ │ ├── base_local_datasource_test.dart
161 | │ │ │ └── todo_local_datasource_test.dart
162 | │ │ └── remote
163 | │ │ ├── __mock__
164 | │ │ │ ├── http_client_mock.dart
165 | │ │ │ └── todo_remote_datasource_mock.dart
166 | │ │ └── todo_remote_datasource_test.dart
167 | │ ├── models
168 | │ │ ├── __mock__
169 | │ │ │ └── todo_model_data.dart
170 | │ │ └── todo_model_test.dart
171 | │ └── repositories
172 | │ ├── __mock__
173 | │ │ ├── todo_json_data.dart
174 | │ │ └── todo_repository_mock.dart
175 | │ └── todo_repository_impl_test.dart
176 | ├── domain
177 | │ ├── entities
178 | │ │ └── __mock__
179 | │ │ └── todo_entity_data.dart
180 | │ └── usecases
181 | │ ├── __mock__
182 | │ │ └── todo_usecase_mock.dart
183 | │ └── todo_usecase_test.dart
184 | ├── local_database_test_files
185 | │ ├── database_util_test.hive
186 | │ ├── database_util_test.lock
187 | │ ├── testbox.hive
188 | │ ├── testbox.lock
189 | │ ├── todo.hive
190 | │ └── todo.lock
191 | └── presentation
192 | ├── app_test.dart
193 | └── journey
194 | ├── dashboard
195 | │ └── dashboard_screen_test.dart
196 | └── todo
197 | ├── bloc
198 | │ ├── __mock__
199 | │ │ └── todo_bloc_mock.dart
200 | │ └── todo_bloc_test.dart
201 | ├── create_todo
202 | │ └── create_todo_screen_test.dart
203 | ├── todo_list
204 | │ ├── todo_list_screen_test.dart
205 | │ └── widgets
206 | │ └── todo_item_test.dart
207 | └── todo_routes_test.dart
208 |
209 | ```
210 |
211 | # How to run
212 |
213 | `flutter run`
214 |
215 | In case of addition to injector file,
216 | run `flutter pub run build_runner build --delete-conflicting-outputs`
217 |
218 | ## How to test
219 |
220 | `flutter test --coverage`
221 | To see percentage
222 | `lcov -r coverage/lcov.info "*/__test*__/*" "*.g.dart" -o coverage/lcov_cleaned.info`
223 | To see coverage of each file in html view
224 | `genhtml coverage/lcov_cleaned.info -o coverage`
--------------------------------------------------------------------------------
/analysis_options.yaml:
--------------------------------------------------------------------------------
1 | include: package:pedantic/analysis_options.yaml
2 |
3 | analyzer:
4 | strong-mode:
5 | implicit-dynamic: true
6 | errors:
7 | # allow having TODOs in the code
8 | todo: ignore
9 | omit_local_variable_types: ignore
10 | missing_required_param: error
11 | avoid_print: error
12 | exclude:
13 | # exclude files
14 | - lib/**.g.dart
15 | enable-experiment:
16 | - extension-methods
17 |
18 | linter:
19 | rules:
20 | - unnecessary_const
21 | - always_declare_return_types
22 | - always_put_control_body_on_new_line
23 | - always_require_non_null_named_parameters
24 | - valid_regexps
25 | - void_checks
26 | - annotate_overrides
27 | - prefer_single_quotes
28 | - avoid_as
29 | - avoid_empty_else
30 | - avoid_print
31 | - avoid_field_initializers_in_const_classes
32 | - avoid_init_to_null
33 | - avoid_null_checks_in_equality_operators
34 | - avoid_returning_null
35 | - avoid_returning_null_for_void
36 | - avoid_return_types_on_setters
37 | - avoid_returning_null_for_future
38 | - avoid_returning_this
39 | - avoid_single_cascade_in_expression_statements
40 | - await_only_futures
41 | - camel_case_types
42 | - avoid_void_async
43 | - cascade_invocations
44 | - close_sinks
45 | - cancel_subscriptions
46 | - constant_identifier_names
47 | - curly_braces_in_flow_control_structures
48 | - directives_ordering
49 | - prefer_spread_collections
50 | - prefer_constructors_over_static_methods
51 | - empty_statements
52 | - empty_catches
53 | - empty_constructor_bodies
54 | - unnecessary_getters_setters
55 | - file_names
56 | - implementation_imports
57 | - invariant_booleans
58 | - library_names
59 | - library_prefixes
60 | - literal_only_boolean_expressions
61 | - no_adjacent_strings_in_list
62 | - no_duplicate_case_values
63 | - null_closures
64 | - one_member_abstracts
65 | - only_throw_errors
66 | - package_names
67 | - package_prefixed_library_names
68 | - prefer_adjacent_string_concatenation
69 | - prefer_asserts_in_initializer_lists
70 | - prefer_asserts_with_message
71 | - prefer_conditional_assignment
72 | - prefer_const_constructors
73 | - prefer_const_declarations
74 | - prefer_const_literals_to_create_immutables
75 | - prefer_contains
76 | - prefer_final_fields
77 | - prefer_final_in_for_each
78 | - prefer_final_locals
79 | - prefer_for_elements_to_map_fromIterable
80 | - prefer_generic_function_type_aliases
81 | - prefer_if_null_operators
82 | - prefer_initializing_formals
83 | - prefer_inlined_adds
84 | - prefer_interpolation_to_compose_strings
85 | - prefer_iterable_whereType
86 | - prefer_null_aware_operators
87 | - prefer_typing_uninitialized_variables
88 | - provide_deprecation_message
89 | - recursive_getters
90 | - slash_for_doc_comments
91 | - sort_child_properties_last
92 | - sort_pub_dependencies
93 | - sort_unnamed_constructors_first
94 | - test_types_in_equals
95 | - type_annotate_public_apis
96 | - type_init_formals
97 | - unawaited_futures
98 | - unnecessary_await_in_return
99 | - unnecessary_brace_in_string_interps
100 | - unnecessary_new
101 | - unnecessary_null_aware_assignments
102 | - unnecessary_null_in_if_null_operators
103 | - unnecessary_overrides
104 | - unnecessary_parenthesis
105 | - unnecessary_this
106 | - unrelated_type_equality_checks
107 | - unsafe_html
108 | - use_full_hex_values_for_flutter_colors
109 | - use_rethrow_when_possible
110 | - use_setters_to_change_properties
111 | - use_string_buffers
112 |
113 | # nice to have
114 | - avoid_double_and_int_checks
115 | - avoid_bool_literals_in_conditional_expressions
116 | - avoid_function_literals_in_foreach_calls
117 | - unnecessary_lambdas
118 | - flutter_style_todos
119 | - join_return_with_assignment
120 | - lines_longer_than_80_chars
121 | - prefer_foreach
122 | - use_to_and_as_if_applicable
123 |
--------------------------------------------------------------------------------
/android/.gitignore:
--------------------------------------------------------------------------------
1 | gradle-wrapper.jar
2 | /.gradle
3 | /captures/
4 | /gradlew
5 | /gradlew.bat
6 | /local.properties
7 | GeneratedPluginRegistrant.java
8 |
9 | # Remember to never publicly share your keystore.
10 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
11 | key.properties
12 |
--------------------------------------------------------------------------------
/android/app/build.gradle:
--------------------------------------------------------------------------------
1 | def localProperties = new Properties()
2 | def localPropertiesFile = rootProject.file('local.properties')
3 | if (localPropertiesFile.exists()) {
4 | localPropertiesFile.withReader('UTF-8') { reader ->
5 | localProperties.load(reader)
6 | }
7 | }
8 |
9 | def flutterRoot = localProperties.getProperty('flutter.sdk')
10 | if (flutterRoot == null) {
11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
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 | apply plugin: 'com.android.application'
25 | apply plugin: 'kotlin-android'
26 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
27 |
28 | android {
29 | compileSdkVersion 29
30 |
31 | sourceSets {
32 | main.java.srcDirs += 'src/main/kotlin'
33 | }
34 |
35 | lintOptions {
36 | disable 'InvalidPackage'
37 | }
38 |
39 | defaultConfig {
40 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
41 | applicationId "com.example.clean_code_architecture_flutter"
42 | minSdkVersion 16
43 | targetSdkVersion 29
44 | versionCode flutterVersionCode.toInteger()
45 | versionName flutterVersionName
46 | }
47 |
48 | buildTypes {
49 | release {
50 | // TODO: Add your own signing config for the release build.
51 | // Signing with the debug keys for now, so `flutter run --release` works.
52 | signingConfig signingConfigs.debug
53 | }
54 | }
55 | }
56 |
57 | flutter {
58 | source '../..'
59 | }
60 |
61 | dependencies {
62 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
63 | }
64 |
--------------------------------------------------------------------------------
/android/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
8 |
12 |
19 |
23 |
27 |
32 |
36 |
37 |
38 |
39 |
40 |
41 |
43 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/android/app/src/main/kotlin/com/example/clean_code_architecture_flutter/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.example.clean_code_architecture_flutter
2 |
3 | import io.flutter.embedding.android.FlutterActivity
4 |
5 | class MainActivity: FlutterActivity() {
6 | }
7 |
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RashmiRanganathan/clean-code-architecture-flutter/0ded9d03c1fc8cdc5b9947502613e136907fcbea/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RashmiRanganathan/clean-code-architecture-flutter/0ded9d03c1fc8cdc5b9947502613e136907fcbea/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RashmiRanganathan/clean-code-architecture-flutter/0ded9d03c1fc8cdc5b9947502613e136907fcbea/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RashmiRanganathan/clean-code-architecture-flutter/0ded9d03c1fc8cdc5b9947502613e136907fcbea/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RashmiRanganathan/clean-code-architecture-flutter/0ded9d03c1fc8cdc5b9947502613e136907fcbea/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/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/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | ext.kotlin_version = '1.3.50'
3 | repositories {
4 | google()
5 | jcenter()
6 | }
7 |
8 | dependencies {
9 | classpath 'com.android.tools.build:gradle:3.5.0'
10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
11 | }
12 | }
13 |
14 | allprojects {
15 | repositories {
16 | google()
17 | jcenter()
18 | }
19 | }
20 |
21 | rootProject.buildDir = '../build'
22 | subprojects {
23 | project.buildDir = "${rootProject.buildDir}/${project.name}"
24 | }
25 | subprojects {
26 | project.evaluationDependsOn(':app')
27 | }
28 |
29 | task clean(type: Delete) {
30 | delete rootProject.buildDir
31 | }
32 |
--------------------------------------------------------------------------------
/android/clean_code_architecture_flutter_android.iml:
--------------------------------------------------------------------------------
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 |
--------------------------------------------------------------------------------
/android/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx1536M
2 | android.useAndroidX=true
3 | android.enableJetifier=true
4 | android.enableR8=true
5 |
--------------------------------------------------------------------------------
/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-5.6.2-all.zip
7 |
--------------------------------------------------------------------------------
/android/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
3 | def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
4 | def properties = new Properties()
5 |
6 | assert localPropertiesFile.exists()
7 | localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
8 |
9 | def flutterSdkPath = properties.getProperty("flutter.sdk")
10 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
11 | apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"
12 |
--------------------------------------------------------------------------------
/build.yaml:
--------------------------------------------------------------------------------
1 | targets:
2 | $default:
3 | builders:
4 | kiwi:
5 |
--------------------------------------------------------------------------------
/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/.last_build_id:
--------------------------------------------------------------------------------
1 | 288cb429972f2f1686fcb168c26731e4
--------------------------------------------------------------------------------
/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 | 8.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, '9.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 | end
36 |
37 | post_install do |installer|
38 | installer.pods_project.targets.each do |target|
39 | flutter_additional_ios_build_settings(target)
40 | end
41 | end
42 |
--------------------------------------------------------------------------------
/ios/Podfile.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - Flutter (1.0.0)
3 | - path_provider (0.0.1):
4 | - Flutter
5 |
6 | DEPENDENCIES:
7 | - Flutter (from `Flutter`)
8 | - path_provider (from `.symlinks/plugins/path_provider/ios`)
9 |
10 | EXTERNAL SOURCES:
11 | Flutter:
12 | :path: Flutter
13 | path_provider:
14 | :path: ".symlinks/plugins/path_provider/ios"
15 |
16 | SPEC CHECKSUMS:
17 | Flutter: 0e3d915762c693b495b44d77113d4970485de6ec
18 | path_provider: abfe2b5c733d04e238b0d8691db0cfd63a27a93c
19 |
20 | PODFILE CHECKSUM: aafe91acc616949ddb318b77800a7f51bffa2a4c
21 |
22 | COCOAPODS: 1.9.3
23 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
11 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
12 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
13 | 8777303A04A2C15502806CCF /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3A8E061F546688E33C44414F /* Pods_Runner.framework */; };
14 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
15 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
16 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
17 | /* End PBXBuildFile section */
18 |
19 | /* Begin PBXCopyFilesBuildPhase section */
20 | 9705A1C41CF9048500538489 /* Embed Frameworks */ = {
21 | isa = PBXCopyFilesBuildPhase;
22 | buildActionMask = 2147483647;
23 | dstPath = "";
24 | dstSubfolderSpec = 10;
25 | files = (
26 | );
27 | name = "Embed Frameworks";
28 | runOnlyForDeploymentPostprocessing = 0;
29 | };
30 | /* End PBXCopyFilesBuildPhase section */
31 |
32 | /* Begin PBXFileReference section */
33 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; };
34 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; };
35 | 3A8E061F546688E33C44414F /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
36 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; };
37 | 6B5B24F3CC635585318E2D01 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; };
38 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; };
39 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
40 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; };
41 | 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; };
42 | 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; };
43 | 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
44 | 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
45 | 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
46 | 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
47 | 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
48 | C065135A50BBE2E57DF7DF58 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; };
49 | F115696FB03984342899D26A /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; };
50 | /* End PBXFileReference section */
51 |
52 | /* Begin PBXFrameworksBuildPhase section */
53 | 97C146EB1CF9000F007C117D /* Frameworks */ = {
54 | isa = PBXFrameworksBuildPhase;
55 | buildActionMask = 2147483647;
56 | files = (
57 | 8777303A04A2C15502806CCF /* Pods_Runner.framework in Frameworks */,
58 | );
59 | runOnlyForDeploymentPostprocessing = 0;
60 | };
61 | /* End PBXFrameworksBuildPhase section */
62 |
63 | /* Begin PBXGroup section */
64 | 82803B68AAC682D741438F3C /* Pods */ = {
65 | isa = PBXGroup;
66 | children = (
67 | F115696FB03984342899D26A /* Pods-Runner.debug.xcconfig */,
68 | C065135A50BBE2E57DF7DF58 /* Pods-Runner.release.xcconfig */,
69 | 6B5B24F3CC635585318E2D01 /* Pods-Runner.profile.xcconfig */,
70 | );
71 | name = Pods;
72 | path = Pods;
73 | sourceTree = "";
74 | };
75 | 9740EEB11CF90186004384FC /* Flutter */ = {
76 | isa = PBXGroup;
77 | children = (
78 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
79 | 9740EEB21CF90195004384FC /* Debug.xcconfig */,
80 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
81 | 9740EEB31CF90195004384FC /* Generated.xcconfig */,
82 | );
83 | name = Flutter;
84 | sourceTree = "";
85 | };
86 | 97C146E51CF9000F007C117D = {
87 | isa = PBXGroup;
88 | children = (
89 | 9740EEB11CF90186004384FC /* Flutter */,
90 | 97C146F01CF9000F007C117D /* Runner */,
91 | 97C146EF1CF9000F007C117D /* Products */,
92 | 82803B68AAC682D741438F3C /* Pods */,
93 | F1CDD7AB7D7759796C8AE235 /* Frameworks */,
94 | );
95 | sourceTree = "";
96 | };
97 | 97C146EF1CF9000F007C117D /* Products */ = {
98 | isa = PBXGroup;
99 | children = (
100 | 97C146EE1CF9000F007C117D /* Runner.app */,
101 | );
102 | name = Products;
103 | sourceTree = "";
104 | };
105 | 97C146F01CF9000F007C117D /* Runner */ = {
106 | isa = PBXGroup;
107 | children = (
108 | 97C146FA1CF9000F007C117D /* Main.storyboard */,
109 | 97C146FD1CF9000F007C117D /* Assets.xcassets */,
110 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
111 | 97C147021CF9000F007C117D /* Info.plist */,
112 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
113 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
114 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */,
115 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */,
116 | );
117 | path = Runner;
118 | sourceTree = "";
119 | };
120 | F1CDD7AB7D7759796C8AE235 /* Frameworks */ = {
121 | isa = PBXGroup;
122 | children = (
123 | 3A8E061F546688E33C44414F /* Pods_Runner.framework */,
124 | );
125 | name = Frameworks;
126 | sourceTree = "";
127 | };
128 | /* End PBXGroup section */
129 |
130 | /* Begin PBXNativeTarget section */
131 | 97C146ED1CF9000F007C117D /* Runner */ = {
132 | isa = PBXNativeTarget;
133 | buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
134 | buildPhases = (
135 | 4F1C452EBEBB0DA6D06EF4D5 /* [CP] Check Pods Manifest.lock */,
136 | 9740EEB61CF901F6004384FC /* Run Script */,
137 | 97C146EA1CF9000F007C117D /* Sources */,
138 | 97C146EB1CF9000F007C117D /* Frameworks */,
139 | 97C146EC1CF9000F007C117D /* Resources */,
140 | 9705A1C41CF9048500538489 /* Embed Frameworks */,
141 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */,
142 | D7D3C94B5E32A095D0FC9092 /* [CP] Embed Pods Frameworks */,
143 | );
144 | buildRules = (
145 | );
146 | dependencies = (
147 | );
148 | name = Runner;
149 | productName = Runner;
150 | productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
151 | productType = "com.apple.product-type.application";
152 | };
153 | /* End PBXNativeTarget section */
154 |
155 | /* Begin PBXProject section */
156 | 97C146E61CF9000F007C117D /* Project object */ = {
157 | isa = PBXProject;
158 | attributes = {
159 | LastUpgradeCheck = 1020;
160 | ORGANIZATIONNAME = "";
161 | TargetAttributes = {
162 | 97C146ED1CF9000F007C117D = {
163 | CreatedOnToolsVersion = 7.3.1;
164 | LastSwiftMigration = 1100;
165 | };
166 | };
167 | };
168 | buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
169 | compatibilityVersion = "Xcode 9.3";
170 | developmentRegion = en;
171 | hasScannedForEncodings = 0;
172 | knownRegions = (
173 | en,
174 | Base,
175 | );
176 | mainGroup = 97C146E51CF9000F007C117D;
177 | productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
178 | projectDirPath = "";
179 | projectRoot = "";
180 | targets = (
181 | 97C146ED1CF9000F007C117D /* Runner */,
182 | );
183 | };
184 | /* End PBXProject section */
185 |
186 | /* Begin PBXResourcesBuildPhase section */
187 | 97C146EC1CF9000F007C117D /* Resources */ = {
188 | isa = PBXResourcesBuildPhase;
189 | buildActionMask = 2147483647;
190 | files = (
191 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
192 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
193 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
194 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
195 | );
196 | runOnlyForDeploymentPostprocessing = 0;
197 | };
198 | /* End PBXResourcesBuildPhase section */
199 |
200 | /* Begin PBXShellScriptBuildPhase section */
201 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
202 | isa = PBXShellScriptBuildPhase;
203 | buildActionMask = 2147483647;
204 | files = (
205 | );
206 | inputPaths = (
207 | );
208 | name = "Thin Binary";
209 | outputPaths = (
210 | );
211 | runOnlyForDeploymentPostprocessing = 0;
212 | shellPath = /bin/sh;
213 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
214 | };
215 | 4F1C452EBEBB0DA6D06EF4D5 /* [CP] Check Pods Manifest.lock */ = {
216 | isa = PBXShellScriptBuildPhase;
217 | buildActionMask = 2147483647;
218 | files = (
219 | );
220 | inputFileListPaths = (
221 | );
222 | inputPaths = (
223 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
224 | "${PODS_ROOT}/Manifest.lock",
225 | );
226 | name = "[CP] Check Pods Manifest.lock";
227 | outputFileListPaths = (
228 | );
229 | outputPaths = (
230 | "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
231 | );
232 | runOnlyForDeploymentPostprocessing = 0;
233 | shellPath = /bin/sh;
234 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
235 | showEnvVarsInLog = 0;
236 | };
237 | 9740EEB61CF901F6004384FC /* Run Script */ = {
238 | isa = PBXShellScriptBuildPhase;
239 | buildActionMask = 2147483647;
240 | files = (
241 | );
242 | inputPaths = (
243 | );
244 | name = "Run Script";
245 | outputPaths = (
246 | );
247 | runOnlyForDeploymentPostprocessing = 0;
248 | shellPath = /bin/sh;
249 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
250 | };
251 | D7D3C94B5E32A095D0FC9092 /* [CP] Embed Pods Frameworks */ = {
252 | isa = PBXShellScriptBuildPhase;
253 | buildActionMask = 2147483647;
254 | files = (
255 | );
256 | inputPaths = (
257 | "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh",
258 | "${PODS_ROOT}/../Flutter/Flutter.framework",
259 | "${BUILT_PRODUCTS_DIR}/path_provider/path_provider.framework",
260 | );
261 | name = "[CP] Embed Pods Frameworks";
262 | outputPaths = (
263 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Flutter.framework",
264 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/path_provider.framework",
265 | );
266 | runOnlyForDeploymentPostprocessing = 0;
267 | shellPath = /bin/sh;
268 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
269 | showEnvVarsInLog = 0;
270 | };
271 | /* End PBXShellScriptBuildPhase section */
272 |
273 | /* Begin PBXSourcesBuildPhase section */
274 | 97C146EA1CF9000F007C117D /* Sources */ = {
275 | isa = PBXSourcesBuildPhase;
276 | buildActionMask = 2147483647;
277 | files = (
278 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,
279 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
280 | );
281 | runOnlyForDeploymentPostprocessing = 0;
282 | };
283 | /* End PBXSourcesBuildPhase section */
284 |
285 | /* Begin PBXVariantGroup section */
286 | 97C146FA1CF9000F007C117D /* Main.storyboard */ = {
287 | isa = PBXVariantGroup;
288 | children = (
289 | 97C146FB1CF9000F007C117D /* Base */,
290 | );
291 | name = Main.storyboard;
292 | sourceTree = "";
293 | };
294 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {
295 | isa = PBXVariantGroup;
296 | children = (
297 | 97C147001CF9000F007C117D /* Base */,
298 | );
299 | name = LaunchScreen.storyboard;
300 | sourceTree = "";
301 | };
302 | /* End PBXVariantGroup section */
303 |
304 | /* Begin XCBuildConfiguration section */
305 | 249021D3217E4FDB00AE95B9 /* Profile */ = {
306 | isa = XCBuildConfiguration;
307 | buildSettings = {
308 | ALWAYS_SEARCH_USER_PATHS = NO;
309 | CLANG_ANALYZER_NONNULL = YES;
310 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
311 | CLANG_CXX_LIBRARY = "libc++";
312 | CLANG_ENABLE_MODULES = YES;
313 | CLANG_ENABLE_OBJC_ARC = YES;
314 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
315 | CLANG_WARN_BOOL_CONVERSION = YES;
316 | CLANG_WARN_COMMA = YES;
317 | CLANG_WARN_CONSTANT_CONVERSION = YES;
318 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
319 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
320 | CLANG_WARN_EMPTY_BODY = YES;
321 | CLANG_WARN_ENUM_CONVERSION = YES;
322 | CLANG_WARN_INFINITE_RECURSION = YES;
323 | CLANG_WARN_INT_CONVERSION = YES;
324 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
325 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
326 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
327 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
328 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
329 | CLANG_WARN_STRICT_PROTOTYPES = YES;
330 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
331 | CLANG_WARN_UNREACHABLE_CODE = YES;
332 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
333 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
334 | COPY_PHASE_STRIP = NO;
335 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
336 | ENABLE_NS_ASSERTIONS = NO;
337 | ENABLE_STRICT_OBJC_MSGSEND = YES;
338 | GCC_C_LANGUAGE_STANDARD = gnu99;
339 | GCC_NO_COMMON_BLOCKS = YES;
340 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
341 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
342 | GCC_WARN_UNDECLARED_SELECTOR = YES;
343 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
344 | GCC_WARN_UNUSED_FUNCTION = YES;
345 | GCC_WARN_UNUSED_VARIABLE = YES;
346 | IPHONEOS_DEPLOYMENT_TARGET = 9.0;
347 | MTL_ENABLE_DEBUG_INFO = NO;
348 | SDKROOT = iphoneos;
349 | SUPPORTED_PLATFORMS = iphoneos;
350 | TARGETED_DEVICE_FAMILY = "1,2";
351 | VALIDATE_PRODUCT = YES;
352 | };
353 | name = Profile;
354 | };
355 | 249021D4217E4FDB00AE95B9 /* Profile */ = {
356 | isa = XCBuildConfiguration;
357 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
358 | buildSettings = {
359 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
360 | CLANG_ENABLE_MODULES = YES;
361 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
362 | ENABLE_BITCODE = NO;
363 | FRAMEWORK_SEARCH_PATHS = (
364 | "$(inherited)",
365 | "$(PROJECT_DIR)/Flutter",
366 | );
367 | INFOPLIST_FILE = Runner/Info.plist;
368 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
369 | LIBRARY_SEARCH_PATHS = (
370 | "$(inherited)",
371 | "$(PROJECT_DIR)/Flutter",
372 | );
373 | PRODUCT_BUNDLE_IDENTIFIER = com.example.cleanCodeArchitectureFlutter;
374 | PRODUCT_NAME = "$(TARGET_NAME)";
375 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
376 | SWIFT_VERSION = 5.0;
377 | VERSIONING_SYSTEM = "apple-generic";
378 | };
379 | name = Profile;
380 | };
381 | 97C147031CF9000F007C117D /* Debug */ = {
382 | isa = XCBuildConfiguration;
383 | buildSettings = {
384 | ALWAYS_SEARCH_USER_PATHS = NO;
385 | CLANG_ANALYZER_NONNULL = YES;
386 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
387 | CLANG_CXX_LIBRARY = "libc++";
388 | CLANG_ENABLE_MODULES = YES;
389 | CLANG_ENABLE_OBJC_ARC = YES;
390 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
391 | CLANG_WARN_BOOL_CONVERSION = YES;
392 | CLANG_WARN_COMMA = YES;
393 | CLANG_WARN_CONSTANT_CONVERSION = YES;
394 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
395 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
396 | CLANG_WARN_EMPTY_BODY = YES;
397 | CLANG_WARN_ENUM_CONVERSION = YES;
398 | CLANG_WARN_INFINITE_RECURSION = YES;
399 | CLANG_WARN_INT_CONVERSION = YES;
400 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
401 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
402 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
403 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
404 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
405 | CLANG_WARN_STRICT_PROTOTYPES = YES;
406 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
407 | CLANG_WARN_UNREACHABLE_CODE = YES;
408 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
409 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
410 | COPY_PHASE_STRIP = NO;
411 | DEBUG_INFORMATION_FORMAT = dwarf;
412 | ENABLE_STRICT_OBJC_MSGSEND = YES;
413 | ENABLE_TESTABILITY = YES;
414 | GCC_C_LANGUAGE_STANDARD = gnu99;
415 | GCC_DYNAMIC_NO_PIC = NO;
416 | GCC_NO_COMMON_BLOCKS = YES;
417 | GCC_OPTIMIZATION_LEVEL = 0;
418 | GCC_PREPROCESSOR_DEFINITIONS = (
419 | "DEBUG=1",
420 | "$(inherited)",
421 | );
422 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
423 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
424 | GCC_WARN_UNDECLARED_SELECTOR = YES;
425 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
426 | GCC_WARN_UNUSED_FUNCTION = YES;
427 | GCC_WARN_UNUSED_VARIABLE = YES;
428 | IPHONEOS_DEPLOYMENT_TARGET = 9.0;
429 | MTL_ENABLE_DEBUG_INFO = YES;
430 | ONLY_ACTIVE_ARCH = YES;
431 | SDKROOT = iphoneos;
432 | TARGETED_DEVICE_FAMILY = "1,2";
433 | };
434 | name = Debug;
435 | };
436 | 97C147041CF9000F007C117D /* Release */ = {
437 | isa = XCBuildConfiguration;
438 | buildSettings = {
439 | ALWAYS_SEARCH_USER_PATHS = NO;
440 | CLANG_ANALYZER_NONNULL = YES;
441 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
442 | CLANG_CXX_LIBRARY = "libc++";
443 | CLANG_ENABLE_MODULES = YES;
444 | CLANG_ENABLE_OBJC_ARC = YES;
445 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
446 | CLANG_WARN_BOOL_CONVERSION = YES;
447 | CLANG_WARN_COMMA = YES;
448 | CLANG_WARN_CONSTANT_CONVERSION = YES;
449 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
450 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
451 | CLANG_WARN_EMPTY_BODY = YES;
452 | CLANG_WARN_ENUM_CONVERSION = YES;
453 | CLANG_WARN_INFINITE_RECURSION = YES;
454 | CLANG_WARN_INT_CONVERSION = YES;
455 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
456 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
457 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
458 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
459 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
460 | CLANG_WARN_STRICT_PROTOTYPES = YES;
461 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
462 | CLANG_WARN_UNREACHABLE_CODE = YES;
463 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
464 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
465 | COPY_PHASE_STRIP = NO;
466 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
467 | ENABLE_NS_ASSERTIONS = NO;
468 | ENABLE_STRICT_OBJC_MSGSEND = YES;
469 | GCC_C_LANGUAGE_STANDARD = gnu99;
470 | GCC_NO_COMMON_BLOCKS = YES;
471 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
472 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
473 | GCC_WARN_UNDECLARED_SELECTOR = YES;
474 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
475 | GCC_WARN_UNUSED_FUNCTION = YES;
476 | GCC_WARN_UNUSED_VARIABLE = YES;
477 | IPHONEOS_DEPLOYMENT_TARGET = 9.0;
478 | MTL_ENABLE_DEBUG_INFO = NO;
479 | SDKROOT = iphoneos;
480 | SUPPORTED_PLATFORMS = iphoneos;
481 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
482 | TARGETED_DEVICE_FAMILY = "1,2";
483 | VALIDATE_PRODUCT = YES;
484 | };
485 | name = Release;
486 | };
487 | 97C147061CF9000F007C117D /* Debug */ = {
488 | isa = XCBuildConfiguration;
489 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
490 | buildSettings = {
491 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
492 | CLANG_ENABLE_MODULES = YES;
493 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
494 | ENABLE_BITCODE = NO;
495 | FRAMEWORK_SEARCH_PATHS = (
496 | "$(inherited)",
497 | "$(PROJECT_DIR)/Flutter",
498 | );
499 | INFOPLIST_FILE = Runner/Info.plist;
500 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
501 | LIBRARY_SEARCH_PATHS = (
502 | "$(inherited)",
503 | "$(PROJECT_DIR)/Flutter",
504 | );
505 | PRODUCT_BUNDLE_IDENTIFIER = com.example.cleanCodeArchitectureFlutter;
506 | PRODUCT_NAME = "$(TARGET_NAME)";
507 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
508 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
509 | SWIFT_VERSION = 5.0;
510 | VERSIONING_SYSTEM = "apple-generic";
511 | };
512 | name = Debug;
513 | };
514 | 97C147071CF9000F007C117D /* Release */ = {
515 | isa = XCBuildConfiguration;
516 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
517 | buildSettings = {
518 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
519 | CLANG_ENABLE_MODULES = YES;
520 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
521 | ENABLE_BITCODE = NO;
522 | FRAMEWORK_SEARCH_PATHS = (
523 | "$(inherited)",
524 | "$(PROJECT_DIR)/Flutter",
525 | );
526 | INFOPLIST_FILE = Runner/Info.plist;
527 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
528 | LIBRARY_SEARCH_PATHS = (
529 | "$(inherited)",
530 | "$(PROJECT_DIR)/Flutter",
531 | );
532 | PRODUCT_BUNDLE_IDENTIFIER = com.example.cleanCodeArchitectureFlutter;
533 | PRODUCT_NAME = "$(TARGET_NAME)";
534 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
535 | SWIFT_VERSION = 5.0;
536 | VERSIONING_SYSTEM = "apple-generic";
537 | };
538 | name = Release;
539 | };
540 | /* End XCBuildConfiguration section */
541 |
542 | /* Begin XCConfigurationList section */
543 | 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
544 | isa = XCConfigurationList;
545 | buildConfigurations = (
546 | 97C147031CF9000F007C117D /* Debug */,
547 | 97C147041CF9000F007C117D /* Release */,
548 | 249021D3217E4FDB00AE95B9 /* Profile */,
549 | );
550 | defaultConfigurationIsVisible = 0;
551 | defaultConfigurationName = Release;
552 | };
553 | 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = {
554 | isa = XCConfigurationList;
555 | buildConfigurations = (
556 | 97C147061CF9000F007C117D /* Debug */,
557 | 97C147071CF9000F007C117D /* Release */,
558 | 249021D4217E4FDB00AE95B9 /* Profile */,
559 | );
560 | defaultConfigurationIsVisible = 0;
561 | defaultConfigurationName = Release;
562 | };
563 | /* End XCConfigurationList section */
564 | };
565 | rootObject = 97C146E61CF9000F007C117D /* Project object */;
566 | }
567 |
--------------------------------------------------------------------------------
/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 |
32 |
33 |
39 |
40 |
41 |
42 |
43 |
44 |
54 |
56 |
62 |
63 |
64 |
65 |
66 |
67 |
73 |
75 |
81 |
82 |
83 |
84 |
86 |
87 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/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.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "size" : "20x20",
5 | "idiom" : "iphone",
6 | "filename" : "Icon-App-20x20@2x.png",
7 | "scale" : "2x"
8 | },
9 | {
10 | "size" : "20x20",
11 | "idiom" : "iphone",
12 | "filename" : "Icon-App-20x20@3x.png",
13 | "scale" : "3x"
14 | },
15 | {
16 | "size" : "29x29",
17 | "idiom" : "iphone",
18 | "filename" : "Icon-App-29x29@1x.png",
19 | "scale" : "1x"
20 | },
21 | {
22 | "size" : "29x29",
23 | "idiom" : "iphone",
24 | "filename" : "Icon-App-29x29@2x.png",
25 | "scale" : "2x"
26 | },
27 | {
28 | "size" : "29x29",
29 | "idiom" : "iphone",
30 | "filename" : "Icon-App-29x29@3x.png",
31 | "scale" : "3x"
32 | },
33 | {
34 | "size" : "40x40",
35 | "idiom" : "iphone",
36 | "filename" : "Icon-App-40x40@2x.png",
37 | "scale" : "2x"
38 | },
39 | {
40 | "size" : "40x40",
41 | "idiom" : "iphone",
42 | "filename" : "Icon-App-40x40@3x.png",
43 | "scale" : "3x"
44 | },
45 | {
46 | "size" : "60x60",
47 | "idiom" : "iphone",
48 | "filename" : "Icon-App-60x60@2x.png",
49 | "scale" : "2x"
50 | },
51 | {
52 | "size" : "60x60",
53 | "idiom" : "iphone",
54 | "filename" : "Icon-App-60x60@3x.png",
55 | "scale" : "3x"
56 | },
57 | {
58 | "size" : "20x20",
59 | "idiom" : "ipad",
60 | "filename" : "Icon-App-20x20@1x.png",
61 | "scale" : "1x"
62 | },
63 | {
64 | "size" : "20x20",
65 | "idiom" : "ipad",
66 | "filename" : "Icon-App-20x20@2x.png",
67 | "scale" : "2x"
68 | },
69 | {
70 | "size" : "29x29",
71 | "idiom" : "ipad",
72 | "filename" : "Icon-App-29x29@1x.png",
73 | "scale" : "1x"
74 | },
75 | {
76 | "size" : "29x29",
77 | "idiom" : "ipad",
78 | "filename" : "Icon-App-29x29@2x.png",
79 | "scale" : "2x"
80 | },
81 | {
82 | "size" : "40x40",
83 | "idiom" : "ipad",
84 | "filename" : "Icon-App-40x40@1x.png",
85 | "scale" : "1x"
86 | },
87 | {
88 | "size" : "40x40",
89 | "idiom" : "ipad",
90 | "filename" : "Icon-App-40x40@2x.png",
91 | "scale" : "2x"
92 | },
93 | {
94 | "size" : "76x76",
95 | "idiom" : "ipad",
96 | "filename" : "Icon-App-76x76@1x.png",
97 | "scale" : "1x"
98 | },
99 | {
100 | "size" : "76x76",
101 | "idiom" : "ipad",
102 | "filename" : "Icon-App-76x76@2x.png",
103 | "scale" : "2x"
104 | },
105 | {
106 | "size" : "83.5x83.5",
107 | "idiom" : "ipad",
108 | "filename" : "Icon-App-83.5x83.5@2x.png",
109 | "scale" : "2x"
110 | },
111 | {
112 | "size" : "1024x1024",
113 | "idiom" : "ios-marketing",
114 | "filename" : "Icon-App-1024x1024@1x.png",
115 | "scale" : "1x"
116 | }
117 | ],
118 | "info" : {
119 | "version" : 1,
120 | "author" : "xcode"
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RashmiRanganathan/clean-code-architecture-flutter/0ded9d03c1fc8cdc5b9947502613e136907fcbea/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RashmiRanganathan/clean-code-architecture-flutter/0ded9d03c1fc8cdc5b9947502613e136907fcbea/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RashmiRanganathan/clean-code-architecture-flutter/0ded9d03c1fc8cdc5b9947502613e136907fcbea/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RashmiRanganathan/clean-code-architecture-flutter/0ded9d03c1fc8cdc5b9947502613e136907fcbea/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RashmiRanganathan/clean-code-architecture-flutter/0ded9d03c1fc8cdc5b9947502613e136907fcbea/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RashmiRanganathan/clean-code-architecture-flutter/0ded9d03c1fc8cdc5b9947502613e136907fcbea/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RashmiRanganathan/clean-code-architecture-flutter/0ded9d03c1fc8cdc5b9947502613e136907fcbea/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RashmiRanganathan/clean-code-architecture-flutter/0ded9d03c1fc8cdc5b9947502613e136907fcbea/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RashmiRanganathan/clean-code-architecture-flutter/0ded9d03c1fc8cdc5b9947502613e136907fcbea/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RashmiRanganathan/clean-code-architecture-flutter/0ded9d03c1fc8cdc5b9947502613e136907fcbea/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RashmiRanganathan/clean-code-architecture-flutter/0ded9d03c1fc8cdc5b9947502613e136907fcbea/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RashmiRanganathan/clean-code-architecture-flutter/0ded9d03c1fc8cdc5b9947502613e136907fcbea/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RashmiRanganathan/clean-code-architecture-flutter/0ded9d03c1fc8cdc5b9947502613e136907fcbea/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RashmiRanganathan/clean-code-architecture-flutter/0ded9d03c1fc8cdc5b9947502613e136907fcbea/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RashmiRanganathan/clean-code-architecture-flutter/0ded9d03c1fc8cdc5b9947502613e136907fcbea/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "LaunchImage.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "LaunchImage@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "LaunchImage@3x.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RashmiRanganathan/clean-code-architecture-flutter/0ded9d03c1fc8cdc5b9947502613e136907fcbea/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RashmiRanganathan/clean-code-architecture-flutter/0ded9d03c1fc8cdc5b9947502613e136907fcbea/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RashmiRanganathan/clean-code-architecture-flutter/0ded9d03c1fc8cdc5b9947502613e136907fcbea/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 |
--------------------------------------------------------------------------------
/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 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | clean_code_architecture_flutter
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | $(FLUTTER_BUILD_NAME)
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | $(FLUTTER_BUILD_NUMBER)
23 | LSRequiresIPhoneOS
24 |
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIMainStoryboardFile
28 | Main
29 | UISupportedInterfaceOrientations
30 |
31 | UIInterfaceOrientationPortrait
32 | UIInterfaceOrientationLandscapeLeft
33 | UIInterfaceOrientationLandscapeRight
34 |
35 | UISupportedInterfaceOrientations~ipad
36 |
37 | UIInterfaceOrientationPortrait
38 | UIInterfaceOrientationPortraitUpsideDown
39 | UIInterfaceOrientationLandscapeLeft
40 | UIInterfaceOrientationLandscapeRight
41 |
42 | UIViewControllerBasedStatusBarAppearance
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/ios/Runner/Runner-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | #import "GeneratedPluginRegistrant.h"
2 |
--------------------------------------------------------------------------------
/lib/common/configs/configuration.dart:
--------------------------------------------------------------------------------
1 | class Configuration {
2 | static const String host = 'https://api-nodejs-todolist.herokuapp.com';
3 | }
4 |
--------------------------------------------------------------------------------
/lib/common/constants/exception_constants.dart:
--------------------------------------------------------------------------------
1 | class ExceptionConstants {
2 | static String unauthorized = 'UNAUTHORIZED';
3 | static String badRequest = 'BAD_REQUEST';
4 | static String forbidden = 'FORBIDDEN';
5 | static String notFound = 'NOT_FOUND';
6 | static String internalServerError = 'INTERNAL_SERVER_ERROR';
7 | static String somethingWentWrong = '"something went wrong"';
8 | }
9 |
--------------------------------------------------------------------------------
/lib/common/constants/http_constants.dart:
--------------------------------------------------------------------------------
1 | class HttpConstants {
2 | static const String contentType = 'Content-Type';
3 | static String authorization = 'Authorization';
4 | static const String jsonContentType = 'application/json';
5 |
6 | // hard-coded value for authorization
7 | static String authorizationValue =
8 | '''Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJfaWQiOiI2MDY3NmVjM2ZlMzcyMzAwMTcwYjFhZGUiLCJpYXQiOjE2MTczOTEyOTl9.cPAFPuOkHq8nw4VWUW_0xrooMZJCH-Ct6J6qgApOug8''';
9 | }
10 |
--------------------------------------------------------------------------------
/lib/common/constants/local_database_type_constants.dart:
--------------------------------------------------------------------------------
1 | /// Order the the ids should be increasing from child most Table to Parent table
2 | class HiveTypeIdConstants {
3 | static const int customerTableId = 0;
4 | }
5 |
6 | class HiveTableNameConstants {
7 | static const todoTableName = 'todo';
8 | }
9 |
--------------------------------------------------------------------------------
/lib/common/constants/route_constants.dart:
--------------------------------------------------------------------------------
1 | class RouteList {
2 | static const String todoList = 'todo-list';
3 | static const String dashbaord = 'dashboard';
4 | static const String createTodo = 'create-todo';
5 | }
6 |
--------------------------------------------------------------------------------
/lib/common/exceptions/bad_request_exception.dart:
--------------------------------------------------------------------------------
1 | import 'package:clean_code_architecture_flutter/common/constants/exception_constants.dart';
2 | import 'package:clean_code_architecture_flutter/common/exceptions/server_exception.dart';
3 |
4 | class BadRequestException extends ServerException {
5 | BadRequestException(String message)
6 | : super(
7 | message: message ?? '',
8 | code: ExceptionConstants.badRequest,
9 | );
10 | }
11 |
--------------------------------------------------------------------------------
/lib/common/exceptions/forbidden_exception.dart:
--------------------------------------------------------------------------------
1 | import 'package:clean_code_architecture_flutter/common/constants/exception_constants.dart';
2 | import 'package:clean_code_architecture_flutter/common/exceptions/server_exception.dart';
3 |
4 | class ForbiddenException extends ServerException {
5 | ForbiddenException(String message)
6 | : super(
7 | message: message ?? '',
8 | code: ExceptionConstants.forbidden,
9 | );
10 | }
11 |
--------------------------------------------------------------------------------
/lib/common/exceptions/server_error_exception.dart:
--------------------------------------------------------------------------------
1 | import 'package:clean_code_architecture_flutter/common/constants/exception_constants.dart';
2 | import 'package:clean_code_architecture_flutter/common/exceptions/server_exception.dart';
3 |
4 | class ServerErrorException extends ServerException {
5 | ServerErrorException(String message)
6 | : super(
7 | message: message ?? '',
8 | code: ExceptionConstants.internalServerError,
9 | );
10 | }
11 |
--------------------------------------------------------------------------------
/lib/common/exceptions/server_exception.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/foundation.dart';
2 |
3 | class ServerException implements Exception {
4 | final String code;
5 | final String message;
6 |
7 | ServerException({@required this.message, this.code});
8 | }
9 |
--------------------------------------------------------------------------------
/lib/common/exceptions/unauthorized_exception.dart:
--------------------------------------------------------------------------------
1 | import 'package:clean_code_architecture_flutter/common/constants/exception_constants.dart';
2 | import 'package:clean_code_architecture_flutter/common/exceptions/server_exception.dart';
3 |
4 | class UnauthorisedException extends ServerException {
5 | UnauthorisedException(String message)
6 | : super(
7 | message: message ?? '',
8 | code: ExceptionConstants.unauthorized,
9 | );
10 | }
11 |
--------------------------------------------------------------------------------
/lib/common/extensions/string_extension.dart:
--------------------------------------------------------------------------------
1 | extension StringExtension on String {}
2 |
--------------------------------------------------------------------------------
/lib/common/http/http_client.dart:
--------------------------------------------------------------------------------
1 | import 'dart:convert';
2 |
3 | import 'package:flutter/material.dart';
4 | import 'package:http/http.dart';
5 |
6 | import 'package:clean_code_architecture_flutter/common/configs/configuration.dart';
7 | import 'package:clean_code_architecture_flutter/common/constants/http_constants.dart';
8 | import 'package:clean_code_architecture_flutter/common/utils/http_utils.dart';
9 |
10 | class HttpClient {
11 | Client client;
12 | String host;
13 | Map header;
14 |
15 | HttpClient({
16 | @required this.host,
17 | this.client,
18 | }) {
19 | client ??= Client();
20 | }
21 |
22 | factory HttpClient.setTodoAPIhost() => HttpClient(host: Configuration.host);
23 |
24 | Uri _getParsedUrl(String path) {
25 | return Uri.parse('$host$path');
26 | }
27 |
28 | Map _generateAuthorizationHeader() => {
29 | HttpConstants.authorization: HttpConstants.authorizationValue,
30 | HttpConstants.contentType: HttpConstants.jsonContentType
31 | };
32 |
33 | Map _generateRequestHeader([
34 | Map overrideHeader = const {},
35 | ]) =>
36 | {
37 | ..._generateAuthorizationHeader(),
38 | ...overrideHeader,
39 | };
40 |
41 | dynamic get(String path) async {
42 | final requestHeader = _generateRequestHeader();
43 |
44 | final Response response = await client.get(
45 | _getParsedUrl(path),
46 | headers: requestHeader,
47 | );
48 |
49 | return HttpUtil.getResponse(
50 | response,
51 | );
52 | }
53 |
54 | dynamic post(String path, dynamic data) async {
55 | final requestHeader = _generateRequestHeader();
56 |
57 | final Response response = await client.post(
58 | _getParsedUrl(path),
59 | body: HttpUtil.encodeRequestBody(
60 | data, requestHeader[HttpConstants.contentType]),
61 | headers: requestHeader,
62 | );
63 |
64 | return HttpUtil.getResponse(
65 | response,
66 | );
67 | }
68 |
69 | dynamic patch(String path, dynamic data) async {
70 | final requestHeader = _generateRequestHeader();
71 |
72 | final Response response = await client.patch(
73 | _getParsedUrl(path),
74 | body: HttpUtil.encodeRequestBody(
75 | data, requestHeader[HttpConstants.contentType]),
76 | headers: requestHeader,
77 | );
78 |
79 | return HttpUtil.getResponse(
80 | response,
81 | );
82 | }
83 |
84 | dynamic put(String path, dynamic data) async {
85 | final requestHeader = _generateRequestHeader();
86 |
87 | final Response response = await client.put(
88 | _getParsedUrl(path),
89 | body: json.encode(data),
90 | headers: requestHeader,
91 | );
92 |
93 | return HttpUtil.getResponse(
94 | response,
95 | );
96 | }
97 |
98 | dynamic delete(String path) async {
99 | final requestHeader = _generateRequestHeader();
100 |
101 | final Response response = await client.delete(
102 | _getParsedUrl(path),
103 | headers: requestHeader,
104 | );
105 |
106 | return HttpUtil.getResponse(response);
107 | }
108 |
109 | dynamic getImage(String url) async {
110 | final Response response = await client.get(url);
111 | return response;
112 | }
113 | }
114 |
--------------------------------------------------------------------------------
/lib/common/injector/injector.dart:
--------------------------------------------------------------------------------
1 | import 'package:kiwi/kiwi.dart';
2 |
3 | abstract class Injector {
4 | static KiwiContainer container = KiwiContainer();
5 |
6 | static final T Function([String name]) resolve = container.resolve;
7 | }
8 |
--------------------------------------------------------------------------------
/lib/common/injector/injector_config.dart:
--------------------------------------------------------------------------------
1 | import 'package:kiwi/kiwi.dart';
2 |
3 | import 'package:clean_code_architecture_flutter/common/http/http_client.dart';
4 | import 'package:clean_code_architecture_flutter/data/datasources/local/local_database/todo_local_datasource.dart';
5 | import 'package:clean_code_architecture_flutter/data/datasources/remote/todo_remote_datasource.dart';
6 | import 'package:clean_code_architecture_flutter/data/repositories/todo_repository_impl.dart';
7 | import 'package:clean_code_architecture_flutter/domain/repositories/todo_repository.dart';
8 | import 'package:clean_code_architecture_flutter/domain/usescases/todo_usecase.dart';
9 | import 'package:clean_code_architecture_flutter/presentation/journey/todo/bloc/todo_bloc.dart';
10 |
11 | part 'injector_config.g.dart';
12 |
13 | abstract class InjectorConfig {
14 | static KiwiContainer container;
15 |
16 | static void setup() {
17 | container = KiwiContainer();
18 | _$InjectorConfig()._configure();
19 | }
20 |
21 | // ignore: type_annotate_public_apis
22 | static final resolve = container.resolve;
23 |
24 | void _configure() {
25 | _configureBlocs();
26 | _configureUsecases();
27 | _configureRepositories();
28 | _configureRemoteDataSources();
29 | _configureLocalDataSources();
30 | _configureCommon();
31 | }
32 |
33 | // ============ BLOCS ============
34 | @Register.singleton(TodoBloc)
35 | void _configureBlocs();
36 |
37 | // ============ USECASES ============
38 | @Register.singleton(TodoUsecase)
39 | void _configureUsecases();
40 |
41 | // ============ REPOSITORIES ============
42 | @Register.singleton(TodoRepository, from: TodoRepositoryImpl)
43 | void _configureRepositories();
44 |
45 | // ============ REMOTE DATASOURCES ============
46 | @Register.singleton(TodoRemoteDatasource)
47 | void _configureRemoteDataSources();
48 |
49 | // ============ LOCAL DATASOURCES ============
50 | @Register.singleton(TodoLocalDatasource)
51 | void _configureLocalDataSources();
52 |
53 | // ============ COMMON ============
54 | @Register.singleton(HttpClient, constructorName: 'setTodoAPIhost')
55 | void _configureCommon();
56 | }
57 |
--------------------------------------------------------------------------------
/lib/common/injector/injector_config.g.dart:
--------------------------------------------------------------------------------
1 | // GENERATED CODE - DO NOT MODIFY BY HAND
2 |
3 | part of 'injector_config.dart';
4 |
5 | // **************************************************************************
6 | // KiwiInjectorGenerator
7 | // **************************************************************************
8 |
9 | class _$InjectorConfig extends InjectorConfig {
10 | void _configureBlocs() {
11 | final KiwiContainer container = KiwiContainer();
12 | container.registerSingleton((c) => TodoBloc(todoUsecase: c()));
13 | }
14 |
15 | void _configureUsecases() {
16 | final KiwiContainer container = KiwiContainer();
17 | container.registerSingleton(
18 | (c) => TodoUsecase(todoRepository: c()));
19 | }
20 |
21 | void _configureRepositories() {
22 | final KiwiContainer container = KiwiContainer();
23 | container.registerSingleton((c) => TodoRepositoryImpl(
24 | todoRemoteDatasource: c(),
25 | todoLocalDatasource: c()));
26 | }
27 |
28 | void _configureRemoteDataSources() {
29 | final KiwiContainer container = KiwiContainer();
30 | container.registerSingleton(
31 | (c) => TodoRemoteDatasource(httpClient: c()));
32 | }
33 |
34 | void _configureLocalDataSources() {
35 | final KiwiContainer container = KiwiContainer();
36 | container.registerSingleton((c) => TodoLocalDatasource());
37 | }
38 |
39 | void _configureCommon() {
40 | final KiwiContainer container = KiwiContainer();
41 | container.registerSingleton((c) => HttpClient.setTodoAPIhost());
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/lib/common/utils/database_util.dart:
--------------------------------------------------------------------------------
1 | import 'dart:io';
2 |
3 | import 'package:hive/hive.dart';
4 | import 'package:path_provider/path_provider.dart';
5 | import 'package:flutter/material.dart';
6 |
7 | class DatabaseUtil {
8 | static Future initDatabase() async {
9 | final Directory directory = await getApplicationDocumentsDirectory();
10 | Hive.init(directory.path);
11 | }
12 |
13 | /// Register our auto generated Adapter to our Hive database
14 | static void registerAdapter(TypeAdapter adapter) {
15 | try {
16 | Hive.registerAdapter(adapter);
17 | } on HiveError catch (error) {
18 | debugPrint(error.toString());
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/lib/common/utils/http_utils.dart:
--------------------------------------------------------------------------------
1 | import 'dart:convert';
2 |
3 | import 'package:http/http.dart';
4 |
5 | import 'package:clean_code_architecture_flutter/common/constants/exception_constants.dart';
6 | import 'package:clean_code_architecture_flutter/common/constants/http_constants.dart';
7 | import 'package:clean_code_architecture_flutter/common/exceptions/bad_request_exception.dart';
8 | import 'package:clean_code_architecture_flutter/common/exceptions/forbidden_exception.dart';
9 | import 'package:clean_code_architecture_flutter/common/exceptions/server_error_exception.dart';
10 | import 'package:clean_code_architecture_flutter/common/exceptions/unauthorized_exception.dart';
11 |
12 | class HttpUtil {
13 | static dynamic encodeRequestBody(dynamic data, String contentType) {
14 | return contentType == HttpConstants.jsonContentType
15 | ? utf8.encode(json.encode(data))
16 | : data;
17 | }
18 |
19 | static String getErroredResult(dynamic result) {
20 | if (result['error'] is String) {
21 | return result['error'];
22 | } else if (result['message'] is String) {
23 | return result['message'];
24 | }
25 | return ExceptionConstants.somethingWentWrong;
26 | }
27 |
28 | static dynamic getResponse(Response response) {
29 | switch (response.statusCode) {
30 | case 200:
31 | case 201:
32 | final responseJson = json.decode(response.body);
33 | return responseJson['data'];
34 | case 204:
35 | return null;
36 | case 400:
37 | throw BadRequestException(
38 | getErroredResult(json.decode(response.body)),
39 | );
40 | case 401:
41 | throw UnauthorisedException(
42 | getErroredResult(json.decode(response.body)),
43 | );
44 | case 403:
45 | throw ForbiddenException(
46 | getErroredResult(json.decode(response.body)),
47 | );
48 | case 500:
49 |
50 | default:
51 | throw ServerErrorException(
52 | getErroredResult(json.decode(response.body)),
53 | );
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/lib/data/datasources/local/local_database/base_local_database.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:hive/hive.dart';
3 |
4 | /// Abstract class takes 2 types.
5 | /// First datatype is used for storing value. [The key is stricted to be String]
6 | /// Second datatype is the model from which the table is extended from. This is
7 | /// used for a overriden function that takes inout as list of model datatype and
8 | /// converts to list of table datatype to insert into database
9 | ///
10 | /// This class contains basic functions such as
11 | /// get, getAll, insertOrUpdateAll, delete, deleteAll
12 | ///
13 | /// Initiate the class with box name.
14 | ///
15 | /// Every extended class should register the adapters in the constructor.
16 | ///
17 | /// Example:
18 | /// ```dart
19 | /// ContactsLocalDataSource() : super(boxName: 'contacts') {
20 | /// DatabaseUtil.registerAdapter(ContactTableAdapter());
21 | /// DatabaseUtil.registerAdapter(
22 | /// AccountContactTableAdapter());
23 | /// }
24 | /// ```
25 | /// Adapter are the hive table adapter which is used for storing data
26 | /// It is generated code by hive.
27 | /// ContactTable will generate its adapter and by default the name will be
28 | /// ContactTableAdapter
29 | abstract class BaseLocalDataSource {
30 | String _boxName;
31 | Future> boxInstance;
32 |
33 | BaseLocalDataSource({
34 | @required String boxName,
35 | }) {
36 | _boxName = boxName;
37 | }
38 |
39 | void _init() {
40 | boxInstance = Hive.openBox(_boxName);
41 | }
42 |
43 | Future> get getBoxInstance async => _openBox();
44 |
45 | Future> getFormattedData();
46 |
47 | Future insertOrUpdateAll(List todos);
48 |
49 | Future> _openBox() async {
50 | final Box box = await boxInstance;
51 | if (box == null || !box.isOpen) {
52 | _init();
53 | return boxInstance;
54 | }
55 | return box;
56 | }
57 |
58 | Future get(String key) async {
59 | final Box box = await _openBox();
60 | return box.get(key);
61 | }
62 |
63 | Future> getAll() async {
64 | final Box box = await _openBox();
65 | return box.toMap().values.toList();
66 | }
67 |
68 | Future put(String key, TableType value) async {
69 | final Box box = await _openBox();
70 | await box.put(key, value);
71 | }
72 |
73 | Future putAll(Map items) async {
74 | final Box box = await _openBox();
75 | await box.putAll(items);
76 | }
77 |
78 | Future delete(String key) async {
79 | final Box box = await _openBox();
80 | await box.delete(key);
81 | }
82 |
83 | Future deleteAll() async {
84 | final Box box = await _openBox();
85 | final List boxKeys = await keys;
86 | await box.deleteAll(boxKeys);
87 | }
88 |
89 | Future> get keys async {
90 | final Box box = await _openBox();
91 | final List result = box.keys.map((k) => k.toString()).toList();
92 | return result;
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/lib/data/datasources/local/local_database/tables/todo_table.dart:
--------------------------------------------------------------------------------
1 | import 'package:clean_code_architecture_flutter/data/models/todo_model.dart';
2 | import 'package:hive/hive.dart';
3 | import 'package:clean_code_architecture_flutter/common/constants/local_database_type_constants.dart';
4 |
5 | part 'todo_table.g.dart';
6 |
7 | @HiveType(typeId: HiveTypeIdConstants.customerTableId)
8 | class TodoTable extends TodoModel {
9 | @override
10 | @HiveField(1)
11 | String id;
12 |
13 | @override
14 | @HiveField(2)
15 | String description;
16 |
17 | @override
18 | @HiveField(3)
19 | bool completed;
20 |
21 | TodoTable({this.id, this.description, this.completed})
22 | : super(
23 | id: id,
24 | description: description,
25 | completed: completed,
26 | );
27 |
28 | factory TodoTable.fromModel(TodoModel model) => TodoTable(
29 | id: model.id,
30 | description: model.description,
31 | completed: model.completed,
32 | );
33 |
34 | static TodoModel toModel(TodoTable table) => TodoModel(
35 | id: table.id,
36 | description: table.description,
37 | completed: table.completed,
38 | );
39 | }
40 |
--------------------------------------------------------------------------------
/lib/data/datasources/local/local_database/tables/todo_table.g.dart:
--------------------------------------------------------------------------------
1 | // GENERATED CODE - DO NOT MODIFY BY HAND
2 |
3 | part of 'todo_table.dart';
4 |
5 | // **************************************************************************
6 | // TypeAdapterGenerator
7 | // **************************************************************************
8 |
9 | class TodoTableAdapter extends TypeAdapter {
10 | @override
11 | final int typeId = 0;
12 |
13 | @override
14 | TodoTable read(BinaryReader reader) {
15 | final numOfFields = reader.readByte();
16 | final fields = {
17 | for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
18 | };
19 | return TodoTable(
20 | id: fields[1] as String,
21 | description: fields[2] as String,
22 | completed: fields[3] as bool,
23 | );
24 | }
25 |
26 | @override
27 | void write(BinaryWriter writer, TodoTable obj) {
28 | writer
29 | ..writeByte(3)
30 | ..writeByte(1)
31 | ..write(obj.id)
32 | ..writeByte(2)
33 | ..write(obj.description)
34 | ..writeByte(3)
35 | ..write(obj.completed);
36 | }
37 |
38 | @override
39 | int get hashCode => typeId.hashCode;
40 |
41 | @override
42 | bool operator ==(Object other) =>
43 | identical(this, other) ||
44 | other is TodoTableAdapter &&
45 | runtimeType == other.runtimeType &&
46 | typeId == other.typeId;
47 | }
48 |
--------------------------------------------------------------------------------
/lib/data/datasources/local/local_database/todo_local_datasource.dart:
--------------------------------------------------------------------------------
1 | import 'package:clean_code_architecture_flutter/common/constants/local_database_type_constants.dart';
2 | import 'package:clean_code_architecture_flutter/common/utils/database_util.dart';
3 | import 'package:clean_code_architecture_flutter/data/datasources/local/local_database/base_local_database.dart';
4 | import 'package:clean_code_architecture_flutter/data/datasources/local/local_database/tables/todo_table.dart';
5 | import 'package:clean_code_architecture_flutter/data/models/todo_model.dart';
6 |
7 | class TodoLocalDatasource extends BaseLocalDataSource {
8 | TodoLocalDatasource() : super(boxName: HiveTableNameConstants.todoTableName) {
9 | DatabaseUtil.registerAdapter(TodoTableAdapter());
10 | }
11 |
12 | @override
13 | Future> getFormattedData() async {
14 | final List data = await getAll();
15 | return data.map(TodoTable.toModel).toList();
16 | }
17 |
18 | Future insertOrUpdateItem(TodoModel todo) async {
19 | await put(todo.id, TodoTable.fromModel(todo));
20 | }
21 |
22 | @override
23 | Future insertOrUpdateAll(List todos) async {
24 | final Map todoMap = {
25 | for (var todo in todos) todo.id: TodoTable.fromModel(todo)
26 | };
27 | await putAll(todoMap);
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/lib/data/datasources/remote/constants/todo_remote_datasource_constants.dart:
--------------------------------------------------------------------------------
1 | class TodoEndpoints {
2 | static const String getCreateUpdateDeletePath = '/task';
3 | }
4 |
--------------------------------------------------------------------------------
/lib/data/datasources/remote/todo_remote_datasource.dart:
--------------------------------------------------------------------------------
1 | import 'package:clean_code_architecture_flutter/common/http/http_client.dart';
2 | import 'package:clean_code_architecture_flutter/data/datasources/remote/constants/todo_remote_datasource_constants.dart';
3 | import 'package:clean_code_architecture_flutter/data/models/todo_model.dart';
4 |
5 | class TodoRemoteDatasource {
6 | final HttpClient httpClient;
7 | TodoRemoteDatasource({this.httpClient});
8 |
9 | Future> getAll() async {
10 | final List data =
11 | await httpClient.get(TodoEndpoints.getCreateUpdateDeletePath);
12 | return TodoModel.fromJsonList(data);
13 | }
14 |
15 | Future create(TodoModel todo) async {
16 | final Map data = await httpClient.post(
17 | TodoEndpoints.getCreateUpdateDeletePath,
18 | todo.toJson(),
19 | );
20 | return TodoModel.fromJson(data);
21 | }
22 |
23 | Future update(TodoModel todo) async {
24 | final Map data = await httpClient.put(
25 | '${TodoEndpoints.getCreateUpdateDeletePath}/${todo.id}',
26 | todo.toJson(),
27 | );
28 | return TodoModel.fromJson(data);
29 | }
30 |
31 | Future delete(String id) async {
32 | final Map data = await httpClient.delete(
33 | '${TodoEndpoints.getCreateUpdateDeletePath}/$id',
34 | );
35 | return TodoModel.fromJson(data);
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/lib/data/models/todo_model.dart:
--------------------------------------------------------------------------------
1 | import 'package:clean_code_architecture_flutter/domain/entities/todo_entity.dart';
2 |
3 | class TodoModel extends TodoEntity {
4 | TodoModel({
5 | String id,
6 | String description,
7 | bool completed,
8 | }) : super(
9 | id: id,
10 | description: description,
11 | completed: completed,
12 | );
13 |
14 | factory TodoModel.fromJson(dynamic json) => TodoModel(
15 | id: json['_id'],
16 | description: json['description'],
17 | completed: json['completed'] ?? false,
18 | );
19 |
20 | static List fromJsonList(List jsonList) =>
21 | jsonList.map((json) => TodoModel.fromJson(json)).toList();
22 |
23 | Map toJson() {
24 | final Map json = {};
25 | if (completed != null) {
26 | json['completed'] = completed;
27 | }
28 | if (description != null) {
29 | json['description'] = description;
30 | }
31 | return json;
32 | }
33 |
34 | TodoModel.castFromEntity(final TodoEntity todo)
35 | : super(
36 | id: todo.id,
37 | description: todo.description,
38 | completed: todo.completed,
39 | );
40 | }
41 |
--------------------------------------------------------------------------------
/lib/data/repositories/todo_repository_impl.dart:
--------------------------------------------------------------------------------
1 | import 'package:pedantic/pedantic.dart';
2 |
3 | import 'package:clean_code_architecture_flutter/data/datasources/local/local_database/todo_local_datasource.dart';
4 | import 'package:clean_code_architecture_flutter/data/datasources/remote/todo_remote_datasource.dart';
5 | import 'package:clean_code_architecture_flutter/data/models/todo_model.dart';
6 | import 'package:clean_code_architecture_flutter/domain/repositories/todo_repository.dart';
7 |
8 | class TodoRepositoryImpl extends TodoRepository {
9 | final TodoRemoteDatasource todoRemoteDatasource;
10 | final TodoLocalDatasource todoLocalDatasource;
11 |
12 | TodoRepositoryImpl({
13 | this.todoRemoteDatasource,
14 | this.todoLocalDatasource,
15 | });
16 |
17 | @override
18 | Future> getAll({bool fromLocal}) async {
19 | List todos = await todoLocalDatasource.getFormattedData();
20 | if (todos.isEmpty || !(fromLocal ?? true)) {
21 | todos = await todoRemoteDatasource.getAll();
22 |
23 | unawaited(Future.wait(
24 | [
25 | todoLocalDatasource.deleteAll(),
26 | todoLocalDatasource.insertOrUpdateAll(todos),
27 | ],
28 | ));
29 | }
30 | return todos;
31 | }
32 |
33 | @override
34 | Future create(TodoModel todoModel) async {
35 | final TodoModel todo = await todoRemoteDatasource.create(todoModel);
36 | if (todo != null) {
37 | await todoLocalDatasource.insertOrUpdateItem(todo);
38 | }
39 | return todo;
40 | }
41 |
42 | @override
43 | Future delete(String id) async {
44 | final TodoModel todo = await todoRemoteDatasource.delete(id);
45 | if (todo != null) {
46 | await todoLocalDatasource.delete(id);
47 | }
48 | }
49 |
50 | @override
51 | Future update(TodoModel model) async {
52 | final TodoModel todo = await todoRemoteDatasource.update(model);
53 | if (todo != null) {
54 | await todoLocalDatasource.insertOrUpdateItem(todo);
55 | }
56 | return todo;
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/lib/domain/entities/todo_entity.dart:
--------------------------------------------------------------------------------
1 | class TodoEntity {
2 | String id;
3 | String description;
4 | bool completed;
5 |
6 | TodoEntity({
7 | this.id,
8 | this.description,
9 | this.completed,
10 | });
11 | }
12 |
--------------------------------------------------------------------------------
/lib/domain/repositories/todo_repository.dart:
--------------------------------------------------------------------------------
1 | import 'package:clean_code_architecture_flutter/data/models/todo_model.dart';
2 | import 'package:clean_code_architecture_flutter/domain/entities/todo_entity.dart';
3 |
4 | abstract class TodoRepository {
5 | Future> getAll({bool fromLocal});
6 |
7 | Future create(TodoModel todo);
8 |
9 | Future update(TodoModel todo);
10 |
11 | Future delete(String id);
12 | }
13 |
--------------------------------------------------------------------------------
/lib/domain/usescases/todo_usecase.dart:
--------------------------------------------------------------------------------
1 | import 'package:clean_code_architecture_flutter/data/models/todo_model.dart';
2 | import 'package:clean_code_architecture_flutter/domain/entities/todo_entity.dart';
3 | import 'package:clean_code_architecture_flutter/domain/repositories/todo_repository.dart';
4 |
5 | class TodoUsecase {
6 | final TodoRepository todoRepository;
7 |
8 | TodoUsecase({this.todoRepository});
9 |
10 | Future> getAll({bool fromLocal}) async =>
11 | todoRepository.getAll(fromLocal: fromLocal);
12 |
13 | Future create(TodoEntity todo) async {
14 | final TodoModel todoModel = TodoModel.castFromEntity(todo);
15 | return todoRepository.create(todoModel);
16 | }
17 |
18 | Future update(TodoEntity todo) async {
19 | final TodoModel todoModel = TodoModel.castFromEntity(todo);
20 | return todoRepository.update(todoModel);
21 | }
22 |
23 | Future delete(String id) async => todoRepository.delete(id);
24 | }
25 |
--------------------------------------------------------------------------------
/lib/main.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | import 'package:clean_code_architecture_flutter/common/injector/injector_config.dart';
4 | import 'package:clean_code_architecture_flutter/common/utils/database_util.dart';
5 | import 'package:clean_code_architecture_flutter/presentation/app.dart';
6 |
7 | Future main() async {
8 | WidgetsFlutterBinding.ensureInitialized();
9 | InjectorConfig.setup();
10 | await DatabaseUtil.initDatabase();
11 |
12 | runApp(App());
13 | }
14 |
--------------------------------------------------------------------------------
/lib/presentation/app.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | import 'package:clean_code_architecture_flutter/common/constants/route_constants.dart';
4 | import 'package:clean_code_architecture_flutter/presentation/routes.dart';
5 | import 'package:clean_code_architecture_flutter/presentation/themes/theme_data.dart';
6 |
7 | class App extends StatelessWidget {
8 | @override
9 | Widget build(BuildContext context) {
10 | return MaterialApp(
11 | title: 'Todo',
12 | debugShowCheckedModeBanner: false,
13 | theme: appTheme(context),
14 | routes: Routes.getAll(),
15 | initialRoute: RouteList.dashbaord,
16 | );
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/lib/presentation/journey/dashboard/dashboard_constants.dart:
--------------------------------------------------------------------------------
1 | class DashboardConstants {
2 | static const elevatedButtonKey = 'go_to_todo_list';
3 | }
4 |
--------------------------------------------------------------------------------
/lib/presentation/journey/dashboard/dashboard_routes.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | import 'package:clean_code_architecture_flutter/common/constants/route_constants.dart';
4 | import 'package:clean_code_architecture_flutter/presentation/journey/dashboard/dashboard_screen.dart';
5 |
6 | class DashboardRoutes {
7 | static Map getAll() {
8 | return {
9 | RouteList.dashbaord: (context) => DashboardScreen(),
10 | };
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/lib/presentation/journey/dashboard/dashboard_screen.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:clean_code_architecture_flutter/common/constants/route_constants.dart';
3 | import 'package:clean_code_architecture_flutter/presentation/journey/dashboard/dashboard_constants.dart';
4 |
5 | class DashboardScreen extends StatelessWidget {
6 | @override
7 | Widget build(BuildContext context) => Scaffold(
8 | appBar: AppBar(
9 | title: const Text('TO-DO'),
10 | centerTitle: true,
11 | ),
12 | body: Center(
13 | child: Column(
14 | mainAxisAlignment: MainAxisAlignment.center,
15 | children: [
16 | Text(
17 | 'Welcome',
18 | style: Theme.of(context).textTheme.headline3,
19 | ),
20 | ElevatedButton(
21 | key: const ValueKey(DashboardConstants.elevatedButtonKey),
22 | onPressed: () {
23 | Navigator.of(context).pushNamed(RouteList.todoList);
24 | },
25 | child: Text(
26 | 'Go',
27 | style: Theme.of(context).textTheme.button,
28 | ),
29 | )
30 | ],
31 | ),
32 | ),
33 | );
34 | }
35 |
--------------------------------------------------------------------------------
/lib/presentation/journey/todo/bloc/todo_bloc.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter_bloc/flutter_bloc.dart';
2 |
3 | import 'package:clean_code_architecture_flutter/domain/entities/todo_entity.dart';
4 | import 'package:clean_code_architecture_flutter/domain/usescases/todo_usecase.dart';
5 |
6 | import 'package:clean_code_architecture_flutter/presentation/journey/todo/bloc/todo_event.dart';
7 | import 'package:clean_code_architecture_flutter/presentation/journey/todo/bloc/todo_state.dart';
8 |
9 | class TodoBloc extends Bloc {
10 | final TodoUsecase todoUsecase;
11 |
12 | TodoBloc({this.todoUsecase});
13 |
14 | @override
15 | TodoState get initialState => InitialTodos();
16 |
17 | @override
18 | Stream mapEventToState(TodoEvent event) async* {
19 | switch (event.runtimeType) {
20 | case FetchTodos:
21 | yield* _mapFetchTodoState(event);
22 | break;
23 | case AddTodo:
24 | yield* _mapAddTodoState(event);
25 | break;
26 | case UpdateTodo:
27 | yield* _mapUpdateTodoState(event);
28 | break;
29 | case DeleteTodo:
30 | yield* _mapDeleteTodoState(event);
31 | break;
32 | default:
33 | }
34 | }
35 |
36 | Stream _mapFetchTodoState(FetchTodos event) async* {
37 | yield LoadingTodos(todos: state.todos);
38 | try {
39 | final todos = await todoUsecase.getAll(fromLocal: event.fromLocal);
40 | yield LoadedTodos(todos: todos);
41 | } catch (e) {
42 | yield ErrorTodos();
43 | }
44 | }
45 |
46 | Stream _mapAddTodoState(AddTodo event) async* {
47 | final todos = state.todos;
48 | yield LoadingTodos(todos: todos);
49 | try {
50 | final todo = TodoEntity(description: event.description);
51 | final updatedTodo = await todoUsecase.create(todo);
52 | todos.add(updatedTodo);
53 | yield LoadedTodos(todos: todos);
54 | } catch (e) {
55 | yield ErrorTodos();
56 | }
57 | }
58 |
59 | Stream _mapUpdateTodoState(UpdateTodo event) async* {
60 | final todos = state.todos;
61 | yield LoadingTodos(todos: todos);
62 | try {
63 | final todo = todos.singleWhere((TodoEntity todo) => todo.id == event.id);
64 | todo.completed = !todo.completed;
65 | final updatedTodo = await todoUsecase.update(todo);
66 | todos[todos.indexWhere((TodoEntity todo) => todo.id == updatedTodo.id)] =
67 | updatedTodo;
68 | yield LoadedTodos(todos: todos);
69 | } catch (e) {
70 | yield ErrorTodos();
71 | }
72 | }
73 |
74 | Stream _mapDeleteTodoState(DeleteTodo event) async* {
75 | final todos = state.todos;
76 | yield LoadingTodos(todos: todos);
77 | try {
78 | await todoUsecase.delete(event.id);
79 | todos.removeWhere((TodoEntity todo) => todo.id == event.id);
80 | yield LoadedTodos(todos: todos);
81 | } catch (e) {
82 | yield ErrorTodos();
83 | }
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/lib/presentation/journey/todo/bloc/todo_event.dart:
--------------------------------------------------------------------------------
1 | import 'package:equatable/equatable.dart';
2 | import 'package:flutter/material.dart';
3 |
4 | @immutable
5 | abstract class TodoEvent extends Equatable {}
6 |
7 | class FetchTodos extends TodoEvent {
8 | final bool fromLocal;
9 | FetchTodos({this.fromLocal});
10 |
11 | @override
12 | List