Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f6ef5828bb
|
||
|
|
f22ba300cb | ||
|
|
5f52b2fc3d
|
||
|
|
f46707f5c1
|
||
|
|
17ff0f8ba1 | ||
|
|
1a3631f691
|
||
|
|
197c5d54e6
|
||
|
|
c7b241de2d
|
||
|
|
94d573a584
|
||
|
|
37e00fe9c4
|
||
|
|
3c8ff373a1
|
||
|
|
640cfaf118
|
||
|
|
7fc3736854
|
||
|
|
29d8ec640f
|
||
|
|
7f9621b4f6
|
||
|
|
7b61f3f08a
|
||
|
|
75a5facfdc
|
||
|
|
c93b7fb5f7 | ||
|
|
aee7060a0b
|
||
|
|
4f49f4931c | ||
|
|
e8172004a3 | ||
|
|
c6d8ca37fe | ||
|
|
e01f47d41a | ||
|
|
7a24a36af0 | ||
|
|
244a286509 | ||
|
|
81a7ca5a1f | ||
|
|
45c7bd6fca | ||
|
|
cd2806b07b | ||
|
|
dd275460f6 | ||
|
|
dc0f0c61c6 | ||
|
|
1e305c75bd
|
||
|
|
9af76b8e1f | ||
|
|
5593620181 | ||
|
|
a19d4bc5ce | ||
|
|
21b18054ba | ||
|
|
ff90af47cd | ||
|
|
3bb57e65f8 | ||
|
|
9d0aac7894 | ||
|
|
a561cbff23 | ||
|
|
fafec78546 | ||
|
|
feca378131 | ||
|
|
f223811f4b
|
||
|
|
ed65489316
|
||
|
|
33797e4dbf | ||
|
|
3aa6d03dd6 | ||
|
|
bf03324fd0 | ||
|
|
5e83c9e74e
|
||
|
|
672aba7084
|
||
|
|
94d7efbe8c
|
||
|
|
5298bd99ed
|
||
|
|
d792f4cbe9 | ||
|
|
098ec9715e | ||
|
|
6d3c64d17c | ||
|
|
c615186f19 | ||
|
|
55e24fb23b | ||
|
|
4d04c3f446 | ||
|
|
a20e4a1715 | ||
|
|
cf9f1ddb65 | ||
|
|
0c141c715e | ||
|
|
d0f59bbf29 | ||
|
|
562f84dd33 | ||
|
|
771f600eb7 |
+36
@@ -0,0 +1,36 @@
|
||||
# Copyright (C) 2022 WYATT GROUP
|
||||
# Please see the AUTHORS file for details.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: default
|
||||
|
||||
steps:
|
||||
- name: quality-check
|
||||
image: git.wyatt-studio.fr/wyatt-foss/flutter-melos:2.9.0
|
||||
commands:
|
||||
- melos run quality-check
|
||||
- melos run publish:validate
|
||||
- name: publish
|
||||
image: git.wyatt-studio.fr/wyatt-foss/flutter-melos:2.9.0
|
||||
commands:
|
||||
- melos run publish:validate
|
||||
|
||||
trigger:
|
||||
branch:
|
||||
- master
|
||||
event:
|
||||
- push
|
||||
@@ -0,0 +1,7 @@
|
||||
repos:
|
||||
- repo: https://github.com/compilerla/conventional-pre-commit
|
||||
rev: v2.1.1
|
||||
hooks:
|
||||
- id: conventional-pre-commit
|
||||
stages: [commit-msg]
|
||||
args: [build, ci, docs, feat, fix, perf, refactor, style, test, chore]
|
||||
@@ -3,6 +3,60 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## 2022-12-13
|
||||
|
||||
### Changes
|
||||
|
||||
---
|
||||
|
||||
Packages with breaking changes:
|
||||
|
||||
- There are no breaking changes in this release.
|
||||
|
||||
Packages with other changes:
|
||||
|
||||
- [`wyatt_authentication_bloc` - `v0.4.1`](#wyatt_authentication_bloc---v041)
|
||||
|
||||
---
|
||||
|
||||
#### `wyatt_authentication_bloc` - `v0.4.1`
|
||||
|
||||
- **REFACTOR**: use fromFirebaseUser factory to parse user.
|
||||
- **REFACTOR**: update deps and re-export them.
|
||||
- **FIX**: fix mock on register.
|
||||
- **FEAT**: add google sign in in signIn cubit.
|
||||
- **FEAT**: add google sign in parameter in firebase data source constructor.
|
||||
- **FEAT**: add google sign_in support (closes #59).
|
||||
- **FEAT**: add reauthenticate, updateEmail and updatePassword.
|
||||
- **DOCS**: add correct header.
|
||||
|
||||
|
||||
## 2022-12-12
|
||||
|
||||
### Changes
|
||||
|
||||
---
|
||||
|
||||
Packages with breaking changes:
|
||||
|
||||
- There are no breaking changes in this release.
|
||||
|
||||
Packages with other changes:
|
||||
|
||||
- [`wyatt_analysis` - `v2.3.0`](#wyatt_analysis---v230)
|
||||
|
||||
---
|
||||
|
||||
#### `wyatt_analysis` - `v2.3.0`
|
||||
|
||||
- **REFACTOR**: follow melos versioning.
|
||||
- **FIX**: change file include to keep coherence.
|
||||
- **FEAT**: exclude generated code, and add dart>2.16 rules.
|
||||
- **FEAT**: add overwrite protection.
|
||||
- **FEAT**: add 2.2.2 files for archive.
|
||||
- **FEAT**: add utils script to easely bump version.
|
||||
|
||||
|
||||
## 2022-12-04
|
||||
|
||||
### Changes
|
||||
|
||||
@@ -171,10 +171,16 @@ Note that your issue will be close after merging on master.
|
||||
Before closing the issue, please check tests and update coverage. You might run :
|
||||
|
||||
```shell
|
||||
melos run test
|
||||
melos run gen_coverage
|
||||
melos run test:all # this will run all tests in this project
|
||||
melos run gen-coverage # this will generate coverage report
|
||||
melos run gen-class-models # this will generate plantuml class diagrams
|
||||
melos run quality-check # this will run all targets generally expected in CI
|
||||
melos run publish:validate # this will run a validation before publish packages
|
||||
melos run publish # this will publish packages
|
||||
```
|
||||
|
||||
> Note that only modified package will be verified and published.
|
||||
|
||||
#### Merge your work
|
||||
|
||||
After closing your issue, some work may have been done on master in the meantime. To keep a clean git history, please rebase before opening a change request.
|
||||
|
||||
+25
-6
@@ -21,8 +21,7 @@ scripts:
|
||||
|
||||
analyze:
|
||||
run: |
|
||||
melos exec -c 10 -- \
|
||||
flutter analyze --fatal-infos
|
||||
melos exec -c 1 -- flutter analyze --fatal-infos
|
||||
description: Run `flutter analyze` for all packages.
|
||||
|
||||
format:
|
||||
@@ -38,18 +37,38 @@ scripts:
|
||||
description: Clean things very deeply with `git clean`.
|
||||
|
||||
test:selective_unit_test:
|
||||
run: melos exec --dir-exists="test" -- flutter test --no-pub --coverage
|
||||
run: melos exec -- flutter test --no-pub --coverage
|
||||
description: Run Flutter tests for a specific package in this project.
|
||||
select-package:
|
||||
flutter: true
|
||||
dir-exists:
|
||||
- test
|
||||
ignore:
|
||||
- '*example*'
|
||||
|
||||
test:
|
||||
test:all:
|
||||
run: melos run test:selective_unit_test --no-select
|
||||
description: Run all Flutter tests in this project.
|
||||
|
||||
gen-coverage: melos exec -- sh "\$MELOS_ROOT_PATH/combine_coverage.sh" && genhtml coverage/lcov.info -o coverage/html
|
||||
|
||||
gen-class-models: melos exec --scope="*wyatt_*" -- dart pub global run dcdg -o models/class-models.puml
|
||||
gen-class-models:
|
||||
run: melos exec -- dart pub global run dcdg -o models/class-models.puml
|
||||
select-package:
|
||||
ignore:
|
||||
- '*example*'
|
||||
|
||||
quality-check:
|
||||
run: |
|
||||
melos clean && \
|
||||
melos bootstrap && \
|
||||
melos run test:all
|
||||
description: Run all targets generally expected in CI for a full local quality check.
|
||||
|
||||
publish:validate:
|
||||
run: melos publish --diff="origin/$DRONE_COMMIT_BRANCH...HEAD" --yes
|
||||
|
||||
# publish:
|
||||
# run: melos publish --diff="origin/$DRONE_COMMIT_BRANCH...HEAD" --no-dry-run --yes
|
||||
|
||||
# Additional cleanup lifecycle script, executed when `melos clean` is run.
|
||||
postclean: >
|
||||
|
||||
@@ -1,3 +1,12 @@
|
||||
## 2.3.0
|
||||
|
||||
- **REFACTOR**: follow melos versioning.
|
||||
- **FIX**: change file include to keep coherence.
|
||||
- **FEAT**: exclude generated code, and add dart>2.16 rules.
|
||||
- **FEAT**: add overwrite protection.
|
||||
- **FEAT**: add 2.2.2 files for archive.
|
||||
- **FEAT**: add utils script to easely bump version.
|
||||
|
||||
## 2.2.2
|
||||
|
||||
- **DOCS**: add publish_to self hosted pub server.
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||

|
||||
|
||||
This package provides lint rules for Dart and Flutter which are used at [Wyatt](https://wyattapp.io) and [Wyatt Studio](https://wyatt-studio.fr). For more information, see the complete list of options in **lib/analysis_options.2.0.0.yaml**.
|
||||
This package provides lint rules for Dart and Flutter which are used at [Wyatt](https://wyattapp.io) and [Wyatt Studio](https://wyatt-studio.fr). For more information, see the complete list of options in **lib/analysis_options.2.3.0.yaml**.
|
||||
|
||||
**Note**: This package was heavily inspired by [pedantic](https://github.com/dart-lang/pedantic), [Very Good Analysis](https://github.com/VeryGoodOpenSource/very_good_analysis) and the official [flutter_lints](https://pub.dev/packages/flutter_lints).
|
||||
|
||||
@@ -29,12 +29,9 @@ This package provides lint rules for Dart and Flutter which are used at [Wyatt](
|
||||
To use the lints, add a dependency in your `pubspec.yaml`:
|
||||
|
||||
```yaml
|
||||
dev_dependencies:
|
||||
wyatt_analysis:
|
||||
git:
|
||||
url: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages
|
||||
ref: wyatt_analysis-v2.0.0
|
||||
path: packages/wyatt_analysis
|
||||
wyatt_analysis:
|
||||
hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub/
|
||||
version: 2.3.0
|
||||
```
|
||||
|
||||
Then, add an include in `analysis_options.yaml`:
|
||||
@@ -52,13 +49,13 @@ include: package:wyatt_analysis/analysis_options.flutter.yaml
|
||||
If you wish to restrict the lint version, specify a version of `analysis_options.yaml` instead:
|
||||
|
||||
```yaml
|
||||
include: package:wyatt_analysis/analysis_options.flutter.2.0.0.yaml
|
||||
include: package:wyatt_analysis/analysis_options.flutter.2.3.0.yaml
|
||||
```
|
||||
|
||||
If you just want **Dart** version:
|
||||
|
||||
```yaml
|
||||
include: package:wyatt_analysis/analysis_options.2.0.0.yaml
|
||||
include: package:wyatt_analysis/analysis_options.2.3.0.yaml
|
||||
```
|
||||
|
||||
## Suppressing Lints
|
||||
|
||||
@@ -0,0 +1,206 @@
|
||||
# Copyright (C) 2022 WYATT GROUP
|
||||
# Please see the AUTHORS file for details.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
analyzer:
|
||||
language:
|
||||
strict-casts: true
|
||||
strict-inference: true
|
||||
strict-raw-types: true
|
||||
|
||||
errors:
|
||||
todo: ignore
|
||||
close_sinks: ignore
|
||||
missing_required_param: error
|
||||
missing_return: error
|
||||
|
||||
exclude:
|
||||
- example/**
|
||||
- lib/l10n/**
|
||||
- lib/generated/**
|
||||
- lib/generated_plugin_registrant.dart
|
||||
- test/.test_coverage.dart
|
||||
|
||||
linter:
|
||||
rules:
|
||||
- always_declare_return_types
|
||||
- always_require_non_null_named_parameters
|
||||
- always_put_control_body_on_new_line
|
||||
- always_put_required_named_parameters_first
|
||||
- always_use_package_imports
|
||||
- annotate_overrides
|
||||
- avoid_bool_literals_in_conditional_expressions
|
||||
- avoid_catching_errors
|
||||
- avoid_double_and_int_checks
|
||||
- avoid_dynamic_calls
|
||||
- avoid_empty_else
|
||||
- avoid_equals_and_hash_code_on_mutable_classes
|
||||
- avoid_escaping_inner_quotes
|
||||
- avoid_field_initializers_in_const_classes
|
||||
- avoid_function_literals_in_foreach_calls
|
||||
- avoid_init_to_null
|
||||
- avoid_js_rounded_ints
|
||||
- avoid_null_checks_in_equality_operators
|
||||
- avoid_positional_boolean_parameters
|
||||
- avoid_private_typedef_functions
|
||||
- avoid_redundant_argument_values
|
||||
- avoid_relative_lib_imports
|
||||
- avoid_renaming_method_parameters
|
||||
- avoid_return_types_on_setters
|
||||
- avoid_returning_null
|
||||
- avoid_returning_null_for_future
|
||||
- avoid_returning_null_for_void
|
||||
- avoid_returning_this
|
||||
- avoid_setters_without_getters
|
||||
- avoid_shadowing_type_parameters
|
||||
- avoid_single_cascade_in_expression_statements
|
||||
- avoid_slow_async_io
|
||||
- avoid_type_to_string
|
||||
- avoid_types_as_parameter_names
|
||||
- avoid_types_on_closure_parameters
|
||||
- avoid_unused_constructor_parameters
|
||||
- avoid_void_async
|
||||
- await_only_futures
|
||||
- camel_case_extensions
|
||||
- camel_case_types
|
||||
- cancel_subscriptions
|
||||
- cascade_invocations
|
||||
- cast_nullable_to_non_nullable
|
||||
- comment_references
|
||||
- conditional_uri_does_not_exist
|
||||
- constant_identifier_names
|
||||
- control_flow_in_finally
|
||||
- curly_braces_in_flow_control_structures
|
||||
- depend_on_referenced_packages
|
||||
- deprecated_consistency
|
||||
- directives_ordering
|
||||
- empty_catches
|
||||
- empty_constructor_bodies
|
||||
- empty_statements
|
||||
- eol_at_end_of_file
|
||||
- exhaustive_cases
|
||||
- file_names
|
||||
- flutter_style_todos
|
||||
- hash_and_equals
|
||||
- implementation_imports
|
||||
- iterable_contains_unrelated_type
|
||||
- join_return_with_assignment
|
||||
- leading_newlines_in_multiline_strings
|
||||
- library_names
|
||||
- library_prefixes
|
||||
- library_private_types_in_public_api
|
||||
- lines_longer_than_80_chars
|
||||
- list_remove_unrelated_type
|
||||
- literal_only_boolean_expressions
|
||||
- missing_whitespace_between_adjacent_strings
|
||||
- no_adjacent_strings_in_list
|
||||
- no_default_cases
|
||||
- no_duplicate_case_values
|
||||
- no_leading_underscores_for_local_identifiers
|
||||
- no_runtimeType_toString
|
||||
- non_constant_identifier_names
|
||||
- noop_primitive_operations
|
||||
- null_check_on_nullable_type_parameter
|
||||
- null_closures
|
||||
- one_member_abstracts
|
||||
- only_throw_errors
|
||||
- overridden_fields
|
||||
- package_api_docs
|
||||
- package_names
|
||||
- package_prefixed_library_names
|
||||
- parameter_assignments
|
||||
- prefer_adjacent_string_concatenation
|
||||
- prefer_asserts_in_initializer_lists
|
||||
- prefer_asserts_with_message
|
||||
- prefer_collection_literals
|
||||
- prefer_conditional_assignment
|
||||
- prefer_const_constructors
|
||||
- prefer_const_constructors_in_immutables
|
||||
- prefer_const_declarations
|
||||
- prefer_const_literals_to_create_immutables
|
||||
- prefer_constructors_over_static_methods
|
||||
- prefer_contains
|
||||
- prefer_equal_for_default_values
|
||||
- prefer_expression_function_bodies
|
||||
- prefer_final_fields
|
||||
- prefer_final_in_for_each
|
||||
- prefer_final_locals
|
||||
- prefer_for_elements_to_map_fromIterable
|
||||
- prefer_function_declarations_over_variables
|
||||
- prefer_generic_function_type_aliases
|
||||
- prefer_if_elements_to_conditional_expressions
|
||||
- prefer_if_null_operators
|
||||
- prefer_initializing_formals
|
||||
- prefer_inlined_adds
|
||||
- prefer_int_literals
|
||||
- prefer_interpolation_to_compose_strings
|
||||
- prefer_is_empty
|
||||
- prefer_is_not_empty
|
||||
- prefer_is_not_operator
|
||||
- prefer_iterable_whereType
|
||||
- prefer_mixin
|
||||
- prefer_null_aware_operators
|
||||
- prefer_null_aware_method_calls
|
||||
- prefer_single_quotes
|
||||
- prefer_spread_collections
|
||||
- prefer_typing_uninitialized_variables
|
||||
- prefer_void_to_null
|
||||
- provide_deprecation_message
|
||||
- recursive_getters
|
||||
- require_trailing_commas
|
||||
- slash_for_doc_comments
|
||||
- sort_unnamed_constructors_first
|
||||
- test_types_in_equals
|
||||
- throw_in_finally
|
||||
- tighten_type_of_initializing_formals
|
||||
- type_annotate_public_apis
|
||||
- type_init_formals
|
||||
- unawaited_futures
|
||||
- unnecessary_await_in_return
|
||||
- unnecessary_brace_in_string_interps
|
||||
- unnecessary_const
|
||||
- unnecessary_constructor_name
|
||||
- unnecessary_getters_setters
|
||||
- unnecessary_lambdas
|
||||
- unnecessary_late
|
||||
- unnecessary_new
|
||||
- unnecessary_null_aware_assignments
|
||||
- unnecessary_null_checks
|
||||
- unnecessary_null_in_if_null_operators
|
||||
- unnecessary_nullable_for_final_variable_declarations
|
||||
- unnecessary_overrides
|
||||
- unnecessary_parenthesis
|
||||
- unnecessary_raw_strings
|
||||
- unnecessary_statements
|
||||
- unnecessary_string_escapes
|
||||
- unnecessary_string_interpolations
|
||||
- unnecessary_this
|
||||
- unrelated_type_equality_checks
|
||||
- unsafe_html
|
||||
- use_enums
|
||||
- use_function_type_syntax_for_parameters
|
||||
- use_if_null_to_convert_nulls_to_bools
|
||||
- use_is_even_rather_than_modulo
|
||||
- use_late_for_private_fields_and_variables
|
||||
- use_named_constants
|
||||
- use_raw_strings
|
||||
- use_rethrow_when_possible
|
||||
- use_setters_to_change_properties
|
||||
- use_string_buffers
|
||||
- use_super_parameters
|
||||
- use_test_throws_matchers
|
||||
- use_to_and_as_if_applicable
|
||||
- valid_regexps
|
||||
- void_checks
|
||||
@@ -0,0 +1,213 @@
|
||||
# Copyright (C) 2022 WYATT GROUP
|
||||
# Please see the AUTHORS file for details.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
analyzer:
|
||||
language:
|
||||
strict-casts: true
|
||||
strict-inference: true
|
||||
strict-raw-types: true
|
||||
|
||||
errors:
|
||||
todo: info
|
||||
close_sinks: ignore
|
||||
missing_required_param: error
|
||||
missing_return: error
|
||||
|
||||
exclude:
|
||||
- lib/l10n/**
|
||||
- lib/generated/**
|
||||
- lib/gen/**
|
||||
- lib/generated_plugin_registrant.dart
|
||||
- test/.test_coverage.dart
|
||||
- '**/*.g.dart'
|
||||
- '**/*.freezed.dart'
|
||||
|
||||
linter:
|
||||
rules:
|
||||
- always_declare_return_types
|
||||
- always_put_control_body_on_new_line
|
||||
- always_put_required_named_parameters_first
|
||||
- always_require_non_null_named_parameters
|
||||
- always_use_package_imports
|
||||
- annotate_overrides
|
||||
- avoid_bool_literals_in_conditional_expressions
|
||||
- avoid_catching_errors
|
||||
- avoid_double_and_int_checks
|
||||
- avoid_dynamic_calls
|
||||
- avoid_empty_else
|
||||
- avoid_equals_and_hash_code_on_mutable_classes
|
||||
- avoid_escaping_inner_quotes
|
||||
- avoid_field_initializers_in_const_classes
|
||||
- avoid_final_parameters
|
||||
- avoid_function_literals_in_foreach_calls
|
||||
- avoid_init_to_null
|
||||
- avoid_js_rounded_ints
|
||||
- avoid_multiple_declarations_per_line
|
||||
- avoid_null_checks_in_equality_operators
|
||||
- avoid_positional_boolean_parameters
|
||||
- avoid_private_typedef_functions
|
||||
- avoid_redundant_argument_values
|
||||
- avoid_relative_lib_imports
|
||||
- avoid_renaming_method_parameters
|
||||
- avoid_return_types_on_setters
|
||||
- avoid_returning_null
|
||||
- avoid_returning_null_for_future
|
||||
- avoid_returning_null_for_void
|
||||
- avoid_returning_this
|
||||
- avoid_setters_without_getters
|
||||
- avoid_shadowing_type_parameters
|
||||
- avoid_single_cascade_in_expression_statements
|
||||
- avoid_slow_async_io
|
||||
- avoid_type_to_string
|
||||
- avoid_types_as_parameter_names
|
||||
- avoid_types_on_closure_parameters
|
||||
- avoid_unused_constructor_parameters
|
||||
- avoid_void_async
|
||||
- await_only_futures
|
||||
- camel_case_extensions
|
||||
- camel_case_types
|
||||
- cancel_subscriptions
|
||||
- cascade_invocations
|
||||
- cast_nullable_to_non_nullable
|
||||
- comment_references
|
||||
- conditional_uri_does_not_exist
|
||||
- constant_identifier_names
|
||||
- control_flow_in_finally
|
||||
- curly_braces_in_flow_control_structures
|
||||
- depend_on_referenced_packages
|
||||
- deprecated_consistency
|
||||
- directives_ordering
|
||||
- empty_catches
|
||||
- empty_constructor_bodies
|
||||
- empty_statements
|
||||
- eol_at_end_of_file
|
||||
- exhaustive_cases
|
||||
- file_names
|
||||
- flutter_style_todos
|
||||
- hash_and_equals
|
||||
- implementation_imports
|
||||
- iterable_contains_unrelated_type
|
||||
- join_return_with_assignment
|
||||
- leading_newlines_in_multiline_strings
|
||||
- library_names
|
||||
- library_prefixes
|
||||
- library_private_types_in_public_api
|
||||
- lines_longer_than_80_chars
|
||||
- list_remove_unrelated_type
|
||||
- literal_only_boolean_expressions
|
||||
- missing_whitespace_between_adjacent_strings
|
||||
- no_adjacent_strings_in_list
|
||||
- no_default_cases
|
||||
- no_duplicate_case_values
|
||||
- no_leading_underscores_for_library_prefixes
|
||||
- no_leading_underscores_for_local_identifiers
|
||||
- no_runtimeType_toString
|
||||
- non_constant_identifier_names
|
||||
- noop_primitive_operations
|
||||
- null_check_on_nullable_type_parameter
|
||||
- null_closures
|
||||
- one_member_abstracts
|
||||
- only_throw_errors
|
||||
- overridden_fields
|
||||
- package_api_docs
|
||||
- package_names
|
||||
- package_prefixed_library_names
|
||||
- parameter_assignments
|
||||
- prefer_adjacent_string_concatenation
|
||||
- prefer_asserts_in_initializer_lists
|
||||
- prefer_asserts_with_message
|
||||
- prefer_collection_literals
|
||||
- prefer_conditional_assignment
|
||||
- prefer_const_constructors
|
||||
- prefer_const_constructors_in_immutables
|
||||
- prefer_const_declarations
|
||||
- prefer_const_literals_to_create_immutables
|
||||
- prefer_constructors_over_static_methods
|
||||
- prefer_contains
|
||||
- prefer_equal_for_default_values
|
||||
- prefer_expression_function_bodies
|
||||
- prefer_final_fields
|
||||
- prefer_final_in_for_each
|
||||
- prefer_final_locals
|
||||
- prefer_for_elements_to_map_fromIterable
|
||||
- prefer_function_declarations_over_variables
|
||||
- prefer_generic_function_type_aliases
|
||||
- prefer_if_elements_to_conditional_expressions
|
||||
- prefer_if_null_operators
|
||||
- prefer_initializing_formals
|
||||
- prefer_inlined_adds
|
||||
- prefer_int_literals
|
||||
- prefer_interpolation_to_compose_strings
|
||||
- prefer_is_empty
|
||||
- prefer_is_not_empty
|
||||
- prefer_is_not_operator
|
||||
- prefer_iterable_whereType
|
||||
- prefer_mixin
|
||||
- prefer_null_aware_method_calls
|
||||
- prefer_null_aware_operators
|
||||
- prefer_single_quotes
|
||||
- prefer_spread_collections
|
||||
- prefer_typing_uninitialized_variables
|
||||
- prefer_void_to_null
|
||||
- provide_deprecation_message
|
||||
- recursive_getters
|
||||
- require_trailing_commas
|
||||
- slash_for_doc_comments
|
||||
- sort_constructors_first
|
||||
- sort_unnamed_constructors_first
|
||||
- test_types_in_equals
|
||||
- throw_in_finally
|
||||
- tighten_type_of_initializing_formals
|
||||
- type_annotate_public_apis
|
||||
- type_init_formals
|
||||
- unawaited_futures
|
||||
- unnecessary_await_in_return
|
||||
- unnecessary_brace_in_string_interps
|
||||
- unnecessary_const
|
||||
- unnecessary_constructor_name
|
||||
- unnecessary_getters_setters
|
||||
- unnecessary_lambdas
|
||||
- unnecessary_late
|
||||
- unnecessary_new
|
||||
- unnecessary_null_aware_assignments
|
||||
- unnecessary_null_checks
|
||||
- unnecessary_null_in_if_null_operators
|
||||
- unnecessary_nullable_for_final_variable_declarations
|
||||
- unnecessary_overrides
|
||||
- unnecessary_parenthesis
|
||||
- unnecessary_raw_strings
|
||||
- unnecessary_statements
|
||||
- unnecessary_string_escapes
|
||||
- unnecessary_string_interpolations
|
||||
- unnecessary_this
|
||||
- unnecessary_to_list_in_spreads
|
||||
- unrelated_type_equality_checks
|
||||
- unsafe_html
|
||||
- use_enums
|
||||
- use_function_type_syntax_for_parameters
|
||||
- use_if_null_to_convert_nulls_to_bools
|
||||
- use_is_even_rather_than_modulo
|
||||
- use_late_for_private_fields_and_variables
|
||||
- use_named_constants
|
||||
- use_raw_strings
|
||||
- use_rethrow_when_possible
|
||||
- use_setters_to_change_properties
|
||||
- use_string_buffers
|
||||
- use_super_parameters
|
||||
- use_test_throws_matchers
|
||||
- use_to_and_as_if_applicable
|
||||
- valid_regexps
|
||||
- void_checks
|
||||
@@ -14,7 +14,7 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
include: package:wyatt_analysis/analysis_options.2.1.1.yaml
|
||||
include: package:wyatt_analysis/analysis_options.2.2.0.yaml
|
||||
|
||||
linter:
|
||||
rules:
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
# Copyright (C) 2022 WYATT GROUP
|
||||
# Please see the AUTHORS file for details.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
include: package:wyatt_analysis/analysis_options.2.2.2.yaml
|
||||
|
||||
linter:
|
||||
rules:
|
||||
- avoid_print
|
||||
- avoid_unnecessary_containers
|
||||
- avoid_web_libraries_in_flutter
|
||||
- no_logic_in_create_state
|
||||
- sized_box_for_whitespace
|
||||
- sized_box_shrink_expand
|
||||
- sort_child_properties_last
|
||||
- use_build_context_synchronously
|
||||
- use_colored_box
|
||||
- use_decorated_box
|
||||
- use_full_hex_values_for_flutter_colors
|
||||
- use_key_in_widget_constructors
|
||||
@@ -0,0 +1,32 @@
|
||||
# Copyright (C) 2022 WYATT GROUP
|
||||
# Please see the AUTHORS file for details.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
include: package:wyatt_analysis/analysis_options.2.3.0.yaml
|
||||
|
||||
linter:
|
||||
rules:
|
||||
- avoid_print
|
||||
- avoid_unnecessary_containers
|
||||
- avoid_web_libraries_in_flutter
|
||||
- no_logic_in_create_state
|
||||
- sized_box_for_whitespace
|
||||
- sized_box_shrink_expand
|
||||
- sort_child_properties_last
|
||||
- use_build_context_synchronously
|
||||
- use_colored_box
|
||||
- use_decorated_box
|
||||
- use_full_hex_values_for_flutter_colors
|
||||
- use_key_in_widget_constructors
|
||||
@@ -1,3 +1,4 @@
|
||||
|
||||
# Copyright (C) 2022 WYATT GROUP
|
||||
# Please see the AUTHORS file for details.
|
||||
#
|
||||
@@ -14,4 +15,5 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
include: package:wyatt_analysis/analysis_options.flutter.2.2.1.yaml
|
||||
include: package:wyatt_analysis/analysis_options.flutter.2.3.0.yaml
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
|
||||
# Copyright (C) 2022 WYATT GROUP
|
||||
# Please see the AUTHORS file for details.
|
||||
#
|
||||
@@ -14,4 +15,5 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
include: package:wyatt_analysis/analysis_options.2.2.1.yaml
|
||||
include: package:wyatt_analysis/analysis_options.2.3.0.yaml
|
||||
|
||||
|
||||
@@ -15,8 +15,7 @@
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
/// Wyatt analyzer settings and best practices
|
||||
/// used internally at [Wyatt](https://wyattapp.io)
|
||||
/// and [Wyatt Studio](https://wyatt-studio.fr).
|
||||
/// used internally at [Wyatt Studio](https://wyatt-studio.fr).
|
||||
library wyatt_analysis;
|
||||
|
||||
const String wyattAnalysisVersion = '2.2.1';
|
||||
const String wyattAnalysisVersion = '2.3.0';
|
||||
|
||||
Executable
+133
@@ -0,0 +1,133 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
# Copyright (C) 2022 WYATT GROUP
|
||||
# Please see the AUTHORS file for details.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
usage="
|
||||
usage:
|
||||
$(basename "$0") <previous_version> <new_version> -- create new analyzer files.
|
||||
|
||||
where:
|
||||
previous_version: last version, for example \`2.3.0\`
|
||||
new_version: new version, for example \`2.4.0\`"
|
||||
|
||||
old=$1
|
||||
new=$2
|
||||
|
||||
if [ -z "$old" ]; then
|
||||
echo "previous_version cannot be null"
|
||||
echo "${usage}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$new" ]; then
|
||||
echo "new_version cannot be null"
|
||||
echo "${usage}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
SCRIPT_PATH="${BASH_SOURCE:-$0}"
|
||||
ABS_SCRIPT_PATH="$(realpath "${SCRIPT_PATH}")"
|
||||
ABS_DIRECTORY="$(dirname "${ABS_SCRIPT_PATH}")"
|
||||
|
||||
LIB="${ABS_DIRECTORY}/lib/wyatt_analysis.dart"
|
||||
OPTIONS="${ABS_DIRECTORY}/lib/analysis_options.yaml"
|
||||
OLD_OPTIONS="${ABS_DIRECTORY}/lib/analysis_options.${old}.yaml"
|
||||
NEW_OPTIONS="${ABS_DIRECTORY}/lib/analysis_options.${new}.yaml"
|
||||
|
||||
OPTIONS_FLUTTER="${ABS_DIRECTORY}/lib/analysis_options.flutter.yaml"
|
||||
OLD_OPTIONS_FLUTTER="${ABS_DIRECTORY}/lib/analysis_options.flutter.${old}.yaml"
|
||||
NEW_OPTIONS_FLUTTER="${ABS_DIRECTORY}/lib/analysis_options.flutter.${new}.yaml"
|
||||
|
||||
if [ ! -e "$OLD_OPTIONS" ]; then
|
||||
echo "analysis_options.${old}.yaml doesn't exists"
|
||||
echo "${usage}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -e "$OLD_OPTIONS_FLUTTER" ]; then
|
||||
echo "analysis_options.flutter.${old}.yaml doesn't exists"
|
||||
echo "${usage}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -e "$NEW_OPTIONS" ]; then
|
||||
echo "analysis_options.${new}.yaml already exists"
|
||||
echo "${usage}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -e "$NEW_OPTIONS_FLUTTER" ]; then
|
||||
echo "analysis_options.flutter.${old}.yaml already exists"
|
||||
echo "${usage}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Copy previous version files
|
||||
cp "${OLD_OPTIONS}" "${NEW_OPTIONS}"
|
||||
cp "${OLD_OPTIONS_FLUTTER}" "${NEW_OPTIONS_FLUTTER}"
|
||||
|
||||
# Search and replace old version string occurences in new files
|
||||
sed -e "s/${old}/${new}/g" "${NEW_OPTIONS_FLUTTER}" > tempfile.tmp
|
||||
mv -f tempfile.tmp "${NEW_OPTIONS_FLUTTER}"
|
||||
|
||||
sed -e "s/${old}/${new}/g" "${LIB}" > tempfile.tmp
|
||||
mv -f tempfile.tmp "${LIB}"
|
||||
|
||||
sed -e "s/${old}/${new}/g" "README.md" > tempfile.tmp
|
||||
mv -f tempfile.tmp "README.md"
|
||||
|
||||
echo "
|
||||
# Copyright (C) 2022 WYATT GROUP
|
||||
# Please see the AUTHORS file for details.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
include: package:wyatt_analysis/analysis_options.${new}.yaml
|
||||
" > "${OPTIONS}"
|
||||
|
||||
echo "
|
||||
# Copyright (C) 2022 WYATT GROUP
|
||||
# Please see the AUTHORS file for details.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
include: package:wyatt_analysis/analysis_options.flutter.${new}.yaml
|
||||
" > "${OPTIONS_FLUTTER}"
|
||||
|
||||
exit 0
|
||||
@@ -1,7 +1,7 @@
|
||||
name: wyatt_analysis
|
||||
description: Lint rules for Dart and Flutter used internally at Wyatt and Wyatt Studio.
|
||||
description: Lint rules for Dart and Flutter used internally at Wyatt Studio.
|
||||
repository: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages/src/branch/master/packages/wyatt_analysis
|
||||
version: 2.2.2
|
||||
version: 2.3.0
|
||||
|
||||
publish_to: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub
|
||||
|
||||
|
||||
+1
-2
@@ -24,9 +24,8 @@ import 'package:wyatt_http_client/wyatt_http_client.dart';
|
||||
import 'package:wyatt_type_utils/wyatt_type_utils.dart';
|
||||
|
||||
class AlbumApiDataSourceImpl extends AlbumRemoteDataSource {
|
||||
final MiddlewareClient _client;
|
||||
|
||||
AlbumApiDataSourceImpl(this._client);
|
||||
final MiddlewareClient _client;
|
||||
|
||||
@override
|
||||
Future<Album> getAlbum(int id) async {
|
||||
|
||||
+1
-2
@@ -24,9 +24,8 @@ import 'package:wyatt_http_client/wyatt_http_client.dart';
|
||||
import 'package:wyatt_type_utils/wyatt_type_utils.dart';
|
||||
|
||||
class PhotoApiDataSourceImpl extends PhotoRemoteDataSource {
|
||||
final MiddlewareClient _client;
|
||||
|
||||
PhotoApiDataSourceImpl(this._client);
|
||||
final MiddlewareClient _client;
|
||||
|
||||
@override
|
||||
Future<Photo> getPhoto(int id) async {
|
||||
|
||||
+3
-3
@@ -24,15 +24,15 @@ import 'package:wyatt_architecture/wyatt_architecture.dart';
|
||||
import 'package:wyatt_type_utils/wyatt_type_utils.dart';
|
||||
|
||||
class PhotoRepositoryImpl extends PhotoRepository {
|
||||
final PhotoRemoteDataSource _photoRemoteDataSource;
|
||||
final AlbumRemoteDataSource _albumRemoteDataSource;
|
||||
final FavoriteLocalDataSource _favoriteLocalDataSource;
|
||||
|
||||
PhotoRepositoryImpl(
|
||||
this._photoRemoteDataSource,
|
||||
this._albumRemoteDataSource,
|
||||
this._favoriteLocalDataSource,
|
||||
);
|
||||
final PhotoRemoteDataSource _photoRemoteDataSource;
|
||||
final AlbumRemoteDataSource _albumRemoteDataSource;
|
||||
final FavoriteLocalDataSource _favoriteLocalDataSource;
|
||||
|
||||
@override
|
||||
FutureOrResult<void> addPhotoToFavorites(Photo photo) => Result.tryCatchAsync(
|
||||
|
||||
+1
-1
@@ -21,9 +21,9 @@ import 'package:architecture_example/domain/repositories/photo_repository.dart';
|
||||
import 'package:wyatt_architecture/wyatt_architecture.dart';
|
||||
|
||||
class AddPhotoToFavorites extends AsyncUseCase<Photo, List<Photo>> {
|
||||
final PhotoRepository _photoRepository;
|
||||
|
||||
AddPhotoToFavorites(this._photoRepository);
|
||||
final PhotoRepository _photoRepository;
|
||||
|
||||
@override
|
||||
FutureOrResult<List<Photo>> execute(Photo? params) async {
|
||||
|
||||
+1
-1
@@ -20,9 +20,9 @@ import 'package:architecture_example/domain/repositories/photo_repository.dart';
|
||||
import 'package:wyatt_architecture/wyatt_architecture.dart';
|
||||
|
||||
class CheckIfPhotoIsInFavorites extends AsyncUseCase<int, bool> {
|
||||
final PhotoRepository _photoRepository;
|
||||
|
||||
CheckIfPhotoIsInFavorites(this._photoRepository);
|
||||
final PhotoRepository _photoRepository;
|
||||
|
||||
@override
|
||||
FutureOrResult<bool> execute(int? params) async =>
|
||||
|
||||
+1
-1
@@ -19,9 +19,9 @@ import 'package:architecture_example/domain/repositories/photo_repository.dart';
|
||||
import 'package:wyatt_architecture/wyatt_architecture.dart';
|
||||
|
||||
class DisplayFavorites extends AsyncUseCase<NoParam, List<Photo>> {
|
||||
final PhotoRepository _photoRepository;
|
||||
|
||||
DisplayFavorites(this._photoRepository);
|
||||
final PhotoRepository _photoRepository;
|
||||
|
||||
@override
|
||||
FutureOrResult<List<Photo>> execute(void params) {
|
||||
|
||||
@@ -21,9 +21,9 @@ import 'package:architecture_example/domain/repositories/photo_repository.dart';
|
||||
import 'package:wyatt_architecture/wyatt_architecture.dart';
|
||||
|
||||
class DisplayPhoto extends AsyncUseCase<int, Photo> {
|
||||
final PhotoRepository _photoRepository;
|
||||
|
||||
DisplayPhoto(this._photoRepository);
|
||||
final PhotoRepository _photoRepository;
|
||||
|
||||
@override
|
||||
FutureOrResult<Photo> execute(int? params) {
|
||||
|
||||
@@ -22,9 +22,9 @@ import 'package:architecture_example/domain/usecases/photos/params/query_paramet
|
||||
import 'package:wyatt_architecture/wyatt_architecture.dart';
|
||||
|
||||
class OpenAlbum extends AsyncUseCase<QueryParameters, List<Photo>> {
|
||||
final PhotoRepository _photoRepository;
|
||||
|
||||
OpenAlbum(this._photoRepository);
|
||||
final PhotoRepository _photoRepository;
|
||||
|
||||
@override
|
||||
FutureOrResult<List<Photo>> execute(QueryParameters? params) {
|
||||
|
||||
+2
-2
@@ -15,9 +15,9 @@
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
class QueryParameters {
|
||||
|
||||
QueryParameters(this.start, this.limit, {this.albumId = -1});
|
||||
final int albumId;
|
||||
final int? start;
|
||||
final int? limit;
|
||||
|
||||
QueryParameters(this.start, this.limit, {this.albumId = -1});
|
||||
}
|
||||
|
||||
+1
-1
@@ -21,9 +21,9 @@ import 'package:architecture_example/domain/repositories/photo_repository.dart';
|
||||
import 'package:wyatt_architecture/wyatt_architecture.dart';
|
||||
|
||||
class RemovePhotoFromFavorites extends AsyncUseCase<int, List<Photo>> {
|
||||
final PhotoRepository _photoRepository;
|
||||
|
||||
RemovePhotoFromFavorites(this._photoRepository);
|
||||
final PhotoRepository _photoRepository;
|
||||
|
||||
@override
|
||||
FutureOrResult<List<Photo>> execute(int? params) async {
|
||||
|
||||
+1
-1
@@ -22,9 +22,9 @@ import 'package:architecture_example/domain/usecases/photos/params/query_paramet
|
||||
import 'package:wyatt_architecture/wyatt_architecture.dart';
|
||||
|
||||
class RetrieveAllAlbums extends AsyncUseCase<QueryParameters, List<Album>> {
|
||||
final PhotoRepository _photoRepository;
|
||||
|
||||
RetrieveAllAlbums(this._photoRepository);
|
||||
final PhotoRepository _photoRepository;
|
||||
|
||||
@override
|
||||
FutureOrResult<List<Album>> execute(QueryParameters? params) {
|
||||
|
||||
+1
-1
@@ -33,7 +33,6 @@ EventTransformer<E> throttleDroppable<E>(Duration duration) =>
|
||||
(events, mapper) => droppable<E>().call(events.throttle(duration), mapper);
|
||||
|
||||
class AlbumBloc extends Bloc<AlbumEvent, AlbumState> {
|
||||
final RetrieveAllAlbums _retrieveAllAlbums;
|
||||
|
||||
AlbumBloc(this._retrieveAllAlbums) : super(const AlbumState()) {
|
||||
on<AlbumFetched>(
|
||||
@@ -41,6 +40,7 @@ class AlbumBloc extends Bloc<AlbumEvent, AlbumState> {
|
||||
transformer: throttleDroppable(throttleDuration),
|
||||
);
|
||||
}
|
||||
final RetrieveAllAlbums _retrieveAllAlbums;
|
||||
|
||||
Future<void> _onAlbumFetched(
|
||||
AlbumFetched event,
|
||||
|
||||
+3
-3
@@ -26,19 +26,19 @@ abstract class PhotoDetailsState extends Equatable {
|
||||
class PhotoDetailsInitial extends PhotoDetailsState {}
|
||||
|
||||
class PhotoDetailsSuccess extends PhotoDetailsState {
|
||||
final Photo photo;
|
||||
final bool isFavorite;
|
||||
|
||||
const PhotoDetailsSuccess(this.photo, {required this.isFavorite});
|
||||
final Photo photo;
|
||||
final bool isFavorite;
|
||||
|
||||
@override
|
||||
List<Object> get props => [photo, isFavorite];
|
||||
}
|
||||
|
||||
class PhotoDetailsFailure extends PhotoDetailsState {
|
||||
final String error;
|
||||
|
||||
const PhotoDetailsFailure(this.error);
|
||||
final String error;
|
||||
|
||||
@override
|
||||
List<Object> get props => [error];
|
||||
|
||||
+1
-1
@@ -23,10 +23,10 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
part 'favorite_checker_state.dart';
|
||||
|
||||
class FavoriteCheckerCubit extends Cubit<FavoriteCheckerState> {
|
||||
final CheckIfPhotoIsInFavorites _checkIfPhotoIsInFavorites;
|
||||
|
||||
FavoriteCheckerCubit(this._checkIfPhotoIsInFavorites)
|
||||
: super(FavoriteCheckerInitial());
|
||||
final CheckIfPhotoIsInFavorites _checkIfPhotoIsInFavorites;
|
||||
|
||||
FutureOr<void> checkIfPhotoIsInFavorites(int photoId) async {
|
||||
final response = await _checkIfPhotoIsInFavorites.call(photoId);
|
||||
|
||||
+3
-3
@@ -10,19 +10,19 @@ abstract class FavoriteCheckerState extends Equatable {
|
||||
class FavoriteCheckerInitial extends FavoriteCheckerState {}
|
||||
|
||||
class FavoriteCheckerSuccess extends FavoriteCheckerState {
|
||||
final int photoId;
|
||||
final bool isFavorite;
|
||||
|
||||
const FavoriteCheckerSuccess(this.photoId, {required this.isFavorite});
|
||||
final int photoId;
|
||||
final bool isFavorite;
|
||||
|
||||
@override
|
||||
List<Object> get props => [photoId, isFavorite];
|
||||
}
|
||||
|
||||
class FavoriteCheckerFailure extends FavoriteCheckerState {
|
||||
final String error;
|
||||
|
||||
const FavoriteCheckerFailure(this.error);
|
||||
final String error;
|
||||
|
||||
@override
|
||||
List<Object> get props => [error];
|
||||
|
||||
+1
-1
@@ -33,7 +33,6 @@ EventTransformer<E> throttleDroppable<E>(Duration duration) =>
|
||||
(events, mapper) => droppable<E>().call(events.throttle(duration), mapper);
|
||||
|
||||
class PhotoBloc extends Bloc<PhotoEvent, PhotoState> {
|
||||
final OpenAlbum _openAlbum;
|
||||
|
||||
PhotoBloc(this._openAlbum) : super(const PhotoState()) {
|
||||
on<PhotoFetched>(
|
||||
@@ -41,6 +40,7 @@ class PhotoBloc extends Bloc<PhotoEvent, PhotoState> {
|
||||
transformer: throttleDroppable(throttleDuration),
|
||||
);
|
||||
}
|
||||
final OpenAlbum _openAlbum;
|
||||
|
||||
Future<void> _onPhotoFetched(
|
||||
PhotoFetched event,
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@ abstract class PhotoEvent extends Equatable {
|
||||
}
|
||||
|
||||
class PhotoFetched extends PhotoEvent {
|
||||
final int albumId;
|
||||
|
||||
const PhotoFetched(this.albumId);
|
||||
final int albumId;
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ dev_dependencies:
|
||||
wyatt_analysis:
|
||||
git:
|
||||
url: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages
|
||||
ref: wyatt_analysis-v2.2.2
|
||||
ref: wyatt_analysis-v2.3.0
|
||||
path: packages/wyatt_analysis
|
||||
|
||||
# For information on the generic Dart part of this file, see the
|
||||
|
||||
@@ -17,9 +17,9 @@
|
||||
import 'package:wyatt_type_utils/wyatt_type_utils.dart';
|
||||
|
||||
abstract class AppException implements Exception {
|
||||
final String? message;
|
||||
|
||||
AppException([this.message]);
|
||||
final String? message;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
|
||||
@@ -24,4 +24,4 @@ dev_dependencies:
|
||||
|
||||
wyatt_analysis:
|
||||
hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub
|
||||
version: ^2.2.2
|
||||
version: ^2.3.0
|
||||
@@ -1,3 +1,14 @@
|
||||
## 0.4.1
|
||||
|
||||
- **REFACTOR**: use fromFirebaseUser factory to parse user.
|
||||
- **REFACTOR**: update deps and re-export them.
|
||||
- **FIX**: fix mock on register.
|
||||
- **FEAT**: add google sign in in signIn cubit.
|
||||
- **FEAT**: add google sign in parameter in firebase data source constructor.
|
||||
- **FEAT**: add google sign_in support (closes #59).
|
||||
- **FEAT**: add reauthenticate, updateEmail and updatePassword.
|
||||
- **DOCS**: add correct header.
|
||||
|
||||
## 0.4.0+3
|
||||
|
||||
- Update a dependency to the latest release.
|
||||
|
||||
@@ -1,4 +1 @@
|
||||
include: package:wyatt_analysis/analysis_options.flutter.yaml
|
||||
|
||||
analyzer:
|
||||
exclude: "!example/**"
|
||||
@@ -45,5 +45,3 @@ app.*.map.json
|
||||
/android/app/debug
|
||||
/android/app/profile
|
||||
/android/app/release
|
||||
|
||||
firebase_options.dart
|
||||
@@ -4,7 +4,7 @@
|
||||
* -----
|
||||
* File: launch.json
|
||||
* Created Date: 19/08/2022 15:12:25
|
||||
* Last Modified: 19/08/2022 15:22:02
|
||||
* Last Modified: Tue Dec 13 2022
|
||||
* -----
|
||||
* Copyright (c) 2022
|
||||
*/
|
||||
@@ -15,11 +15,18 @@
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "example_router",
|
||||
"name": "Mock",
|
||||
"request": "launch",
|
||||
"type": "dart",
|
||||
"program": "lib/main.dart",
|
||||
"flutterMode": "debug"
|
||||
},
|
||||
{
|
||||
"name": "Firebase",
|
||||
"request": "launch",
|
||||
"type": "dart",
|
||||
"program": "lib/main_firebase.dart",
|
||||
"flutterMode": "debug"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -5,41 +5,30 @@ PODS:
|
||||
- AppAuth/Core (1.6.0)
|
||||
- AppAuth/ExternalUserAgent (1.6.0):
|
||||
- AppAuth/Core
|
||||
- FBAEMKit (14.1.0):
|
||||
- FBSDKCoreKit_Basics (= 14.1.0)
|
||||
- FBSDKCoreKit (14.1.0):
|
||||
- FBAEMKit (= 14.1.0)
|
||||
- FBSDKCoreKit_Basics (= 14.1.0)
|
||||
- FBSDKCoreKit_Basics (14.1.0)
|
||||
- FBSDKLoginKit (14.1.0):
|
||||
- FBSDKCoreKit (= 14.1.0)
|
||||
- Firebase/Auth (10.0.0):
|
||||
- Firebase/Auth (10.3.0):
|
||||
- Firebase/CoreOnly
|
||||
- FirebaseAuth (~> 10.0.0)
|
||||
- Firebase/CoreOnly (10.0.0):
|
||||
- FirebaseCore (= 10.0.0)
|
||||
- firebase_auth (4.1.1):
|
||||
- Firebase/Auth (= 10.0.0)
|
||||
- FirebaseAuth (~> 10.3.0)
|
||||
- Firebase/CoreOnly (10.3.0):
|
||||
- FirebaseCore (= 10.3.0)
|
||||
- firebase_auth (4.2.0):
|
||||
- Firebase/Auth (= 10.3.0)
|
||||
- firebase_core
|
||||
- Flutter
|
||||
- firebase_core (2.1.1):
|
||||
- Firebase/CoreOnly (= 10.0.0)
|
||||
- firebase_core (2.4.0):
|
||||
- Firebase/CoreOnly (= 10.3.0)
|
||||
- Flutter
|
||||
- FirebaseAuth (10.0.0):
|
||||
- FirebaseAuth (10.3.0):
|
||||
- FirebaseCore (~> 10.0)
|
||||
- GoogleUtilities/AppDelegateSwizzler (~> 7.8)
|
||||
- GoogleUtilities/Environment (~> 7.8)
|
||||
- GTMSessionFetcher/Core (~> 2.1)
|
||||
- FirebaseCore (10.0.0):
|
||||
- GTMSessionFetcher/Core (< 4.0, >= 2.1)
|
||||
- FirebaseCore (10.3.0):
|
||||
- FirebaseCoreInternal (~> 10.0)
|
||||
- GoogleUtilities/Environment (~> 7.8)
|
||||
- GoogleUtilities/Logger (~> 7.8)
|
||||
- FirebaseCoreInternal (10.1.0):
|
||||
- FirebaseCoreInternal (10.3.0):
|
||||
- "GoogleUtilities/NSData+zlib (~> 7.8)"
|
||||
- Flutter (1.0.0)
|
||||
- flutter_facebook_auth (4.4.1):
|
||||
- FBSDKLoginKit (= 14.1.0)
|
||||
- Flutter
|
||||
- google_sign_in_ios (0.0.1):
|
||||
- Flutter
|
||||
- GoogleSignIn (~> 6.2)
|
||||
@@ -47,47 +36,36 @@ PODS:
|
||||
- AppAuth (~> 1.5)
|
||||
- GTMAppAuth (~> 1.3)
|
||||
- GTMSessionFetcher/Core (< 3.0, >= 1.1)
|
||||
- GoogleUtilities/AppDelegateSwizzler (7.8.0):
|
||||
- GoogleUtilities/AppDelegateSwizzler (7.10.0):
|
||||
- GoogleUtilities/Environment
|
||||
- GoogleUtilities/Logger
|
||||
- GoogleUtilities/Network
|
||||
- GoogleUtilities/Environment (7.8.0):
|
||||
- GoogleUtilities/Environment (7.10.0):
|
||||
- PromisesObjC (< 3.0, >= 1.2)
|
||||
- GoogleUtilities/Logger (7.8.0):
|
||||
- GoogleUtilities/Logger (7.10.0):
|
||||
- GoogleUtilities/Environment
|
||||
- GoogleUtilities/Network (7.8.0):
|
||||
- GoogleUtilities/Network (7.10.0):
|
||||
- GoogleUtilities/Logger
|
||||
- "GoogleUtilities/NSData+zlib"
|
||||
- GoogleUtilities/Reachability
|
||||
- "GoogleUtilities/NSData+zlib (7.8.0)"
|
||||
- GoogleUtilities/Reachability (7.8.0):
|
||||
- "GoogleUtilities/NSData+zlib (7.10.0)"
|
||||
- GoogleUtilities/Reachability (7.10.0):
|
||||
- GoogleUtilities/Logger
|
||||
- GTMAppAuth (1.3.1):
|
||||
- AppAuth/Core (~> 1.6)
|
||||
- GTMSessionFetcher/Core (< 3.0, >= 1.5)
|
||||
- GTMSessionFetcher/Core (2.1.0)
|
||||
- GTMSessionFetcher/Core (2.3.0)
|
||||
- PromisesObjC (2.1.1)
|
||||
- sign_in_with_apple (0.0.1):
|
||||
- Flutter
|
||||
- twitter_login (0.0.1):
|
||||
- Flutter
|
||||
|
||||
DEPENDENCIES:
|
||||
- firebase_auth (from `.symlinks/plugins/firebase_auth/ios`)
|
||||
- firebase_core (from `.symlinks/plugins/firebase_core/ios`)
|
||||
- Flutter (from `Flutter`)
|
||||
- flutter_facebook_auth (from `.symlinks/plugins/flutter_facebook_auth/ios`)
|
||||
- google_sign_in_ios (from `.symlinks/plugins/google_sign_in_ios/ios`)
|
||||
- sign_in_with_apple (from `.symlinks/plugins/sign_in_with_apple/ios`)
|
||||
- twitter_login (from `.symlinks/plugins/twitter_login/ios`)
|
||||
|
||||
SPEC REPOS:
|
||||
trunk:
|
||||
- AppAuth
|
||||
- FBAEMKit
|
||||
- FBSDKCoreKit
|
||||
- FBSDKCoreKit_Basics
|
||||
- FBSDKLoginKit
|
||||
- Firebase
|
||||
- FirebaseAuth
|
||||
- FirebaseCore
|
||||
@@ -105,37 +83,24 @@ EXTERNAL SOURCES:
|
||||
:path: ".symlinks/plugins/firebase_core/ios"
|
||||
Flutter:
|
||||
:path: Flutter
|
||||
flutter_facebook_auth:
|
||||
:path: ".symlinks/plugins/flutter_facebook_auth/ios"
|
||||
google_sign_in_ios:
|
||||
:path: ".symlinks/plugins/google_sign_in_ios/ios"
|
||||
sign_in_with_apple:
|
||||
:path: ".symlinks/plugins/sign_in_with_apple/ios"
|
||||
twitter_login:
|
||||
:path: ".symlinks/plugins/twitter_login/ios"
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
AppAuth: 8fca6b5563a5baef2c04bee27538025e4ceb2add
|
||||
FBAEMKit: a899515e45476027f73aef377b5cffadcd56ca3a
|
||||
FBSDKCoreKit: 24f8bc8d3b5b2a8c5c656a1329492a12e8efa792
|
||||
FBSDKCoreKit_Basics: 6e578c9bdc7aa1365dbbbde633c9ebb536bcaa98
|
||||
FBSDKLoginKit: 787de205d524c3a4b17d527916f1d066e4361660
|
||||
Firebase: 1b810f3d0c0532e27a48f1961f8c0400a668a2cf
|
||||
firebase_auth: dd33e93fce72a1c72040f7380dacf06e89db5705
|
||||
firebase_core: 5c0bb0ca7d0e70480a68a6e9ad9bf55d1edd5305
|
||||
FirebaseAuth: 493382cf533cc45e2862b00e9aa4cfe4c98daf71
|
||||
FirebaseCore: 97f48a3a567a72b8d4daa0f03c3aadb78df4e995
|
||||
FirebaseCoreInternal: 96d75228e10fd369564da51bd898414eb0f54df5
|
||||
Firebase: f92fc551ead69c94168d36c2b26188263860acd9
|
||||
firebase_auth: 579a0dc15451491cc83fccaa5102296635f24938
|
||||
firebase_core: 6f2f753e316765799d88568232ed59e300ff53db
|
||||
FirebaseAuth: 0e415d29d846c1dce2fb641e46f35e9888d9bec6
|
||||
FirebaseCore: 988754646ab3bd4bdcb740f1bfe26b9f6c0d5f2a
|
||||
FirebaseCoreInternal: 29b76f784d607df8b2a1259d73c3f04f1210137b
|
||||
Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
|
||||
flutter_facebook_auth: 361ac7a57263ebf327f26089507ead0d66558ee8
|
||||
google_sign_in_ios: 4f85eb9f937450765c8573bb85fd8cd6a5af675c
|
||||
GoogleSignIn: 5651ce3a61e56ca864160e79b484cd9ed3f49b7a
|
||||
GoogleUtilities: 1d20a6ad97ef46f67bbdec158ce00563a671ebb7
|
||||
GoogleUtilities: bad72cb363809015b1f7f19beb1f1cd23c589f95
|
||||
GTMAppAuth: 0ff230db599948a9ad7470ca667337803b3fc4dd
|
||||
GTMSessionFetcher: ffbb25ec00ebcb5201adab0a56d808f6f1902d9f
|
||||
GTMSessionFetcher: 3a63d75eecd6aa32c2fc79f578064e1214dfdec2
|
||||
PromisesObjC: ab77feca74fa2823e7af4249b8326368e61014cb
|
||||
sign_in_with_apple: f3bf75217ea4c2c8b91823f225d70230119b8440
|
||||
twitter_login: 2794db69b7640681171b17b3c2c84ad9dfb4a57f
|
||||
|
||||
PODFILE CHECKSUM: ef19549a9bc3046e7bb7d2fab4d021637c0c58a3
|
||||
|
||||
|
||||
@@ -28,6 +28,17 @@
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIMainStoryboardFile</key>
|
||||
<string>Main</string>
|
||||
<key>CFBundleURLTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Editor</string>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>com.googleusercontent.apps.405351917235-2jv4ff02kovoim58f8d6d0rsa14apgkj</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"file_generated_by": "FlutterFire CLI",
|
||||
"purpose": "FirebaseAppID & ProjectID for this Firebase app in this directory",
|
||||
"GOOGLE_APP_ID": "1:136771801992:ios:bcdca68d2b7d227097203d",
|
||||
"FIREBASE_PROJECT_ID": "tchat-beta",
|
||||
"GCM_SENDER_ID": "136771801992"
|
||||
"GOOGLE_APP_ID": "1:405351917235:ios:869f0ad8ace08db899f2c6",
|
||||
"FIREBASE_PROJECT_ID": "meerabel-dev",
|
||||
"GCM_SENDER_ID": "405351917235"
|
||||
}
|
||||
@@ -1,19 +1,64 @@
|
||||
// Author: Hugo Pointcheval
|
||||
// Email: git@pcl.ovh
|
||||
// -----
|
||||
// File: bootstrap.dart
|
||||
// Created Date: 19/08/2022 15:05:17
|
||||
// Last Modified: Fri Nov 11 2022
|
||||
// -----
|
||||
// Copyright (c) 2022
|
||||
// Copyright (C) 2022 WYATT GROUP
|
||||
// Please see the AUTHORS file for details.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:example_router/core/dependency_injection/get_it.dart';
|
||||
import 'package:example_router/core/utils/app_bloc_observer.dart';
|
||||
import 'package:example_router/firebase_options.dart';
|
||||
import 'package:firebase_core/firebase_core.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
class MockSettings {
|
||||
static MockSettings? _instance;
|
||||
|
||||
/// Data source mode
|
||||
late bool enable = false;
|
||||
|
||||
MockSettings._(this.enable);
|
||||
|
||||
factory MockSettings.enable() {
|
||||
_instance ??= MockSettings._(true);
|
||||
if (_instance!.enable != true) {
|
||||
throw Exception('Mock already initialized in: ${_instance!.enable}');
|
||||
}
|
||||
return _instance!;
|
||||
}
|
||||
|
||||
factory MockSettings.disable() {
|
||||
_instance ??= MockSettings._(false);
|
||||
if (_instance!.enable != false) {
|
||||
throw Exception('Mock already initialized in: ${_instance!.enable}');
|
||||
}
|
||||
return _instance!;
|
||||
}
|
||||
|
||||
static bool isEnable() {
|
||||
if (_instance == null) {
|
||||
throw Exception('MockSettings not initialized!');
|
||||
}
|
||||
return _instance!.enable == true;
|
||||
}
|
||||
|
||||
static bool isDisable() {
|
||||
return !isEnable();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> bootstrap(FutureOr<Widget> Function() builder) async {
|
||||
await runZonedGuarded(
|
||||
() async {
|
||||
@@ -23,6 +68,12 @@ Future<void> bootstrap(FutureOr<Widget> Function() builder) async {
|
||||
FlutterError.onError = (details) {
|
||||
debugPrint(details.toString());
|
||||
};
|
||||
|
||||
if (MockSettings.isDisable()) {
|
||||
await Firebase.initializeApp(
|
||||
options: DefaultFirebaseOptions.currentPlatform,
|
||||
);
|
||||
}
|
||||
await GetItInitializer.init();
|
||||
|
||||
runApp(await builder());
|
||||
|
||||
@@ -1,12 +1,20 @@
|
||||
// Author: Hugo Pointcheval
|
||||
// Email: git@pcl.ovh
|
||||
// -----
|
||||
// File: form_field.dart
|
||||
// Created Date: 19/08/2022 11:52:33
|
||||
// Last Modified: 19/08/2022 16:35:39
|
||||
// -----
|
||||
// Copyright (c) 2022
|
||||
// Copyright (C) 2022 WYATT GROUP
|
||||
// Please see the AUTHORS file for details.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
abstract class AppFormField {
|
||||
static const oldPassword = 'oldPassword';
|
||||
static const confirmedPassword = 'confirmedPassword';
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
// Copyright (C) 2022 WYATT GROUP
|
||||
// Please see the AUTHORS file for details.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
abstract class AppFormName {
|
||||
static const editProfile = 'editProfile';
|
||||
}
|
||||
+28
-22
@@ -14,6 +14,8 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import 'package:example_router/bootstrap.dart';
|
||||
import 'package:example_router/firebase_options.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart';
|
||||
import 'package:wyatt_type_utils/wyatt_type_utils.dart';
|
||||
@@ -24,28 +26,32 @@ abstract class GetItInitializer {
|
||||
static Future<void> init() async {
|
||||
getIt
|
||||
..registerLazySingleton<AuthenticationRemoteDataSource>(
|
||||
() => AuthenticationMockDataSourceImpl(registeredAccounts: [
|
||||
Pair(
|
||||
AccountModel(
|
||||
uid: '1',
|
||||
emailVerified: true,
|
||||
isAnonymous: false,
|
||||
providerId: 'wyatt',
|
||||
email: 'toto@test.fr',
|
||||
),
|
||||
'toto1234',
|
||||
),
|
||||
Pair(
|
||||
AccountModel(
|
||||
uid: '2',
|
||||
emailVerified: false,
|
||||
isAnonymous: false,
|
||||
providerId: 'wyatt',
|
||||
email: 'tata@test.fr',
|
||||
),
|
||||
'tata1234',
|
||||
),
|
||||
]),
|
||||
MockSettings.isEnable()
|
||||
? () => AuthenticationMockDataSourceImpl(registeredAccounts: [
|
||||
Pair(
|
||||
AccountModel(
|
||||
uid: '1',
|
||||
emailVerified: true,
|
||||
isAnonymous: false,
|
||||
providerId: 'wyatt',
|
||||
email: 'toto@test.fr',
|
||||
),
|
||||
'toto1234',
|
||||
),
|
||||
Pair(
|
||||
AccountModel(
|
||||
uid: '2',
|
||||
emailVerified: false,
|
||||
isAnonymous: false,
|
||||
providerId: 'wyatt',
|
||||
email: 'tata@test.fr',
|
||||
),
|
||||
'tata1234',
|
||||
),
|
||||
])
|
||||
: () => AuthenticationFirebaseDataSourceImpl(
|
||||
googleSignIn: GoogleSignIn(
|
||||
clientId: DefaultFirebaseOptions.ios.iosClientId)),
|
||||
)
|
||||
..registerLazySingleton<AuthenticationCacheDataSource<int>>(
|
||||
() => AuthenticationCacheDataSourceImpl<int>(),
|
||||
|
||||
@@ -1,12 +1,20 @@
|
||||
// Author: Hugo Pointcheval
|
||||
// Email: git@pcl.ovh
|
||||
// -----
|
||||
// File: router.dart
|
||||
// Created Date: 19/08/2022 11:52:22
|
||||
// Last Modified: 19/08/2022 16:39:07
|
||||
// -----
|
||||
// Copyright (c) 2022
|
||||
// Copyright (C) 2022 WYATT GROUP
|
||||
// Please see the AUTHORS file for details.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import 'package:example_router/presentation/features/edit_profile/edit_profile_page.dart';
|
||||
import 'package:example_router/presentation/features/home/home_page.dart';
|
||||
import 'package:example_router/presentation/features/sign_in/sign_in_page.dart';
|
||||
import 'package:example_router/presentation/features/sign_up/sign_up_page.dart';
|
||||
@@ -75,5 +83,14 @@ class AppRouter {
|
||||
const SubPage(),
|
||||
),
|
||||
),
|
||||
GoRoute(
|
||||
path: '/home/edit',
|
||||
name: EditProfilePage.pageName,
|
||||
pageBuilder: (context, state) => defaultTransition(
|
||||
context,
|
||||
state,
|
||||
const EditProfilePage(),
|
||||
),
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -1,11 +1,18 @@
|
||||
// Author: Hugo Pointcheval
|
||||
// Email: git@pcl.ovh
|
||||
// -----
|
||||
// File: app_bloc_observer.dart
|
||||
// Created Date: 19/08/2022 12:02:23
|
||||
// Last Modified: 19/08/2022 12:02:45
|
||||
// -----
|
||||
// Copyright (c) 2022
|
||||
// Copyright (C) 2022 WYATT GROUP
|
||||
// Please see the AUTHORS file for details.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
+14
-28
@@ -14,33 +14,19 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
part of prompt.framework;
|
||||
import 'package:example_router/core/constants/form_field.dart';
|
||||
import 'package:example_router/core/constants/form_name.dart';
|
||||
import 'package:example_router/core/utils/custom_password.dart';
|
||||
import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart';
|
||||
import 'package:wyatt_form_bloc/wyatt_form_bloc.dart';
|
||||
|
||||
abstract class Widget<T extends dynamic> {
|
||||
int _initLineCount = 0;
|
||||
|
||||
/// Creates the mutable state for this widget
|
||||
@protected
|
||||
@factory
|
||||
State createState();
|
||||
|
||||
State pipeState(State state) => state;
|
||||
|
||||
T prompt() {
|
||||
final state = pipeState(createState())
|
||||
.._widget = this
|
||||
..initState();
|
||||
_initLineCount = state.context.lineCount;
|
||||
state.context.resetLineCount();
|
||||
|
||||
state.build();
|
||||
state.context.incrementBuildCount();
|
||||
|
||||
final dynamic out = state.prompt();
|
||||
state.context.wipe();
|
||||
state.context.erasePreviousLine(_initLineCount);
|
||||
state.dispose();
|
||||
|
||||
return out as T;
|
||||
}
|
||||
abstract class AppForms {
|
||||
static WyattForm getEditProfileForm() => WyattFormImpl(
|
||||
[
|
||||
FormInput(AuthFormField.email, const Email.pure()),
|
||||
FormInput(AuthFormField.password, const CustomPassword.pure()),
|
||||
FormInput(AppFormField.oldPassword, const CustomPassword.pure()),
|
||||
],
|
||||
name: AppFormName.editProfile,
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
// File generated by FlutterFire CLI.
|
||||
// ignore_for_file: lines_longer_than_80_chars, avoid_classes_with_only_static_members
|
||||
import 'package:firebase_core/firebase_core.dart' show FirebaseOptions;
|
||||
import 'package:flutter/foundation.dart'
|
||||
show defaultTargetPlatform, kIsWeb, TargetPlatform;
|
||||
|
||||
/// Default [FirebaseOptions] for use with your Firebase apps.
|
||||
///
|
||||
/// Example:
|
||||
/// ```dart
|
||||
/// import 'firebase_options.dart';
|
||||
/// // ...
|
||||
/// await Firebase.initializeApp(
|
||||
/// options: DefaultFirebaseOptions.currentPlatform,
|
||||
/// );
|
||||
/// ```
|
||||
class DefaultFirebaseOptions {
|
||||
static FirebaseOptions get currentPlatform {
|
||||
if (kIsWeb) {
|
||||
throw UnsupportedError(
|
||||
'DefaultFirebaseOptions have not been configured for web - '
|
||||
'you can reconfigure this by running the FlutterFire CLI again.',
|
||||
);
|
||||
}
|
||||
switch (defaultTargetPlatform) {
|
||||
case TargetPlatform.android:
|
||||
throw UnsupportedError(
|
||||
'DefaultFirebaseOptions have not been configured for android - '
|
||||
'you can reconfigure this by running the FlutterFire CLI again.',
|
||||
);
|
||||
case TargetPlatform.iOS:
|
||||
return ios;
|
||||
case TargetPlatform.macOS:
|
||||
throw UnsupportedError(
|
||||
'DefaultFirebaseOptions have not been configured for macos - '
|
||||
'you can reconfigure this by running the FlutterFire CLI again.',
|
||||
);
|
||||
case TargetPlatform.windows:
|
||||
throw UnsupportedError(
|
||||
'DefaultFirebaseOptions have not been configured for windows - '
|
||||
'you can reconfigure this by running the FlutterFire CLI again.',
|
||||
);
|
||||
case TargetPlatform.linux:
|
||||
throw UnsupportedError(
|
||||
'DefaultFirebaseOptions have not been configured for linux - '
|
||||
'you can reconfigure this by running the FlutterFire CLI again.',
|
||||
);
|
||||
default:
|
||||
throw UnsupportedError(
|
||||
'DefaultFirebaseOptions are not supported for this platform.',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
static const FirebaseOptions ios = FirebaseOptions(
|
||||
apiKey: 'AIzaSyDDmtf0KN7Xw12_pqUsxoBfAxMuvCMmMmk',
|
||||
appId: '1:405351917235:ios:869f0ad8ace08db899f2c6',
|
||||
messagingSenderId: '405351917235',
|
||||
projectId: 'meerabel-dev',
|
||||
storageBucket: 'meerabel-dev.appspot.com',
|
||||
androidClientId:
|
||||
'405351917235-4g1dh3475tq6t1sa2qoh7ol60nf4ta05.apps.googleusercontent.com',
|
||||
iosClientId:
|
||||
'405351917235-2jv4ff02kovoim58f8d6d0rsa14apgkj.apps.googleusercontent.com',
|
||||
iosBundleId: 'com.example.exampleRouter',
|
||||
);
|
||||
}
|
||||
@@ -1,6 +1,23 @@
|
||||
// Copyright (C) 2022 WYATT GROUP
|
||||
// Please see the AUTHORS file for details.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import 'package:example_router/bootstrap.dart';
|
||||
import 'package:example_router/presentation/features/app/app.dart';
|
||||
|
||||
void main() {
|
||||
MockSettings.enable();
|
||||
bootstrap(App.new);
|
||||
}
|
||||
|
||||
+6
-2
@@ -14,6 +14,10 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import 'dart:io';
|
||||
import 'package:example_router/bootstrap.dart';
|
||||
import 'package:example_router/presentation/features/app/app.dart';
|
||||
|
||||
bool get supportsAnsiColor => stdout.supportsAnsiEscapes;
|
||||
void main() {
|
||||
MockSettings.disable();
|
||||
bootstrap(App.new);
|
||||
}
|
||||
@@ -1,11 +1,18 @@
|
||||
// Author: Hugo Pointcheval
|
||||
// Email: git@pcl.ovh
|
||||
// -----
|
||||
// File: app.dart
|
||||
// Created Date: 19/08/2022 12:05:38
|
||||
// Last Modified: Sat Dec 03 2022
|
||||
// -----
|
||||
// Copyright (c) 2022
|
||||
// Copyright (C) 2022 WYATT GROUP
|
||||
// Please see the AUTHORS file for details.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:math';
|
||||
@@ -14,6 +21,7 @@ import 'package:example_router/core/constants/form_field.dart';
|
||||
import 'package:example_router/core/dependency_injection/get_it.dart';
|
||||
import 'package:example_router/core/routes/router.dart';
|
||||
import 'package:example_router/core/utils/custom_password.dart';
|
||||
import 'package:example_router/core/utils/forms.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
@@ -69,7 +77,7 @@ class App extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
AuthenticationState? previous;
|
||||
AuthenticationState<int>? previous;
|
||||
|
||||
final AuthenticationCubit<int> authenticationCubit =
|
||||
AuthenticationCubit(authenticationRepository: authenticationRepository);
|
||||
@@ -85,29 +93,18 @@ class App extends StatelessWidget {
|
||||
redirect: (context, state) {
|
||||
final authState = authenticationCubit.state;
|
||||
|
||||
if (authState != previous) {
|
||||
if (authState.status != previous?.status) {
|
||||
previous = authState;
|
||||
// Check if current user is logged in
|
||||
final loggedIn =
|
||||
authState.status == AuthenticationStatus.authenticated;
|
||||
|
||||
// Checking if current path is onboarding or not
|
||||
final isOnboarding = AppRouter.publicRoutes.contains(state.subloc);
|
||||
|
||||
if (!loggedIn) {
|
||||
if (authState.status == AuthenticationStatus.unauthenticated) {
|
||||
debugPrint('Not logged');
|
||||
if (isOnboarding) {
|
||||
return null;
|
||||
} else {
|
||||
if (!isOnboarding) {
|
||||
return '/';
|
||||
}
|
||||
} else {
|
||||
} else if (authState.status == AuthenticationStatus.authenticated) {
|
||||
debugPrint('Logged');
|
||||
if (isOnboarding) {
|
||||
return '/home';
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
return '/home';
|
||||
}
|
||||
}
|
||||
return null;
|
||||
@@ -116,9 +113,13 @@ class App extends StatelessWidget {
|
||||
|
||||
return MultiRepositoryProvider(
|
||||
providers: [
|
||||
RepositoryProvider<AuthenticationRepository>.value(
|
||||
RepositoryProvider<AuthenticationRepository<int>>.value(
|
||||
value: authenticationRepository,
|
||||
),
|
||||
RepositoryProvider<FormRepository>(
|
||||
create: (context) =>
|
||||
FormRepositoryImpl()..registerForm(AppForms.getEditProfileForm()),
|
||||
),
|
||||
],
|
||||
child: MultiBlocProvider(
|
||||
providers: [
|
||||
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
// Copyright (C) 2022 WYATT GROUP
|
||||
// Please see the AUTHORS file for details.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import 'package:example_router/core/constants/form_field.dart';
|
||||
import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart';
|
||||
import 'package:wyatt_form_bloc/wyatt_form_bloc.dart';
|
||||
import 'package:wyatt_type_utils/wyatt_type_utils.dart';
|
||||
|
||||
class EditProfileCubit extends FormDataCubitImpl {
|
||||
final AuthenticationRepository<int> authenticationRepository;
|
||||
|
||||
EditProfileCubit(
|
||||
super._formRepository,
|
||||
super._formName, {
|
||||
required this.authenticationRepository,
|
||||
}) : super();
|
||||
|
||||
@override
|
||||
Future<void> submit() async {
|
||||
emit(
|
||||
state.copyWith(
|
||||
status: FormStatus.submissionInProgress,
|
||||
),
|
||||
);
|
||||
final user = (await authenticationRepository.getAccount()).ok;
|
||||
|
||||
final form = state.form;
|
||||
final email = form.valueOf<String?>(AuthFormField.email);
|
||||
final oldPassword = form.valueOf<String?>(AppFormField.oldPassword);
|
||||
final newPassword = form.valueOf<String?>(AuthFormField.password);
|
||||
|
||||
if (email.isNullOrEmpty ||
|
||||
oldPassword.isNullOrEmpty ||
|
||||
newPassword.isNullOrEmpty) {
|
||||
emit(
|
||||
state.copyWith(
|
||||
errorMessage: 'An error occured while retrieving data from the form.',
|
||||
status: FormStatus.submissionFailure,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
// await authenticationRepository.signInWithEmailAndPassword(
|
||||
// email: user?.email ?? '',
|
||||
// password: oldPassword ?? '',
|
||||
// );
|
||||
// await authenticationRepository.reauthenticateWithCredential();
|
||||
await authenticationRepository.updateEmail(email: email!);
|
||||
await authenticationRepository.updatePassword(password: newPassword!);
|
||||
} on Exception catch (e) {
|
||||
emit(
|
||||
state.copyWith(
|
||||
status: FormStatus.submissionFailure,
|
||||
errorMessage: e.toString(),
|
||||
),
|
||||
);
|
||||
}
|
||||
emit(state.copyWith(status: FormStatus.submissionSuccess));
|
||||
}
|
||||
}
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
// Copyright (C) 2022 WYATT GROUP
|
||||
// Please see the AUTHORS file for details.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import 'package:example_router/core/constants/form_name.dart';
|
||||
import 'package:example_router/presentation/features/edit_profile/blocs/edit_profile_cubit.dart';
|
||||
import 'package:example_router/presentation/features/edit_profile/widgets/edit_profile_form.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart';
|
||||
import 'package:wyatt_form_bloc/wyatt_form_bloc.dart';
|
||||
|
||||
class EditProfilePage extends StatelessWidget {
|
||||
const EditProfilePage({Key? key}) : super(key: key);
|
||||
|
||||
static String pageName = 'EditProfile';
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: const Text('Edit Profile')),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.all(8),
|
||||
child: SingleChildScrollView(
|
||||
child: BlocProvider<EditProfileCubit>(
|
||||
create: (context) => EditProfileCubit(
|
||||
context.read<FormRepository>(),
|
||||
AppFormName.editProfile,
|
||||
authenticationRepository:
|
||||
context.read<AuthenticationRepository<int>>(),
|
||||
)..dataChanged<String?>(
|
||||
AuthFormField.email,
|
||||
Email.dirty(
|
||||
context
|
||||
.read<AuthenticationCubit<int>>()
|
||||
.state
|
||||
.accountWrapper
|
||||
?.account
|
||||
?.email ??
|
||||
'',
|
||||
),
|
||||
),
|
||||
child: const EditProfileForm(),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
+136
@@ -0,0 +1,136 @@
|
||||
// Copyright (C) 2022 WYATT GROUP
|
||||
// Please see the AUTHORS file for details.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import 'package:example_router/core/constants/form_field.dart';
|
||||
import 'package:example_router/core/utils/custom_password.dart';
|
||||
import 'package:example_router/presentation/features/edit_profile/blocs/edit_profile_cubit.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart';
|
||||
import 'package:wyatt_form_bloc/wyatt_form_bloc.dart';
|
||||
|
||||
class _EmailInput extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return InputBuilderTextController<EditProfileCubit, String?, void>(
|
||||
field: AuthFormField.email,
|
||||
builder: ((context, cubit, state, field, input, controller, extra) {
|
||||
return TextField(
|
||||
onChanged: (email) => cubit.dataChanged<String?>(
|
||||
AuthFormField.email, Email.dirty(email)),
|
||||
keyboardType: TextInputType.emailAddress,
|
||||
controller: controller,
|
||||
decoration: InputDecoration(
|
||||
labelText: 'Email',
|
||||
helperText: '',
|
||||
errorText: input.validator.invalid ? 'Invalid email' : null,
|
||||
),
|
||||
);
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _OldPasswordInput extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return InputBuilder<EditProfileCubit>(
|
||||
field: AppFormField.oldPassword,
|
||||
builder: ((context, cubit, state, field, input) {
|
||||
return TextField(
|
||||
onChanged: (pwd) => cubit.dataChanged<String?>(
|
||||
AppFormField.oldPassword, CustomPassword.dirty(pwd)),
|
||||
obscureText: true,
|
||||
decoration: InputDecoration(
|
||||
labelText: 'Old Password',
|
||||
helperText: '',
|
||||
errorText: input.validator.invalid ? 'Invalid password' : null,
|
||||
),
|
||||
);
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _NewPasswordInput extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return InputBuilder<EditProfileCubit>(
|
||||
field: AuthFormField.password,
|
||||
builder: ((context, cubit, state, field, input) {
|
||||
return TextField(
|
||||
onChanged: (pwd) => cubit.dataChanged<String?>(
|
||||
AuthFormField.password, CustomPassword.dirty(pwd)),
|
||||
obscureText: true,
|
||||
decoration: InputDecoration(
|
||||
labelText: 'New Password',
|
||||
helperText: '',
|
||||
errorText: input.validator.invalid ? 'Invalid password' : null,
|
||||
),
|
||||
);
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _EditButton extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SubmitBuilder<EditProfileCubit>(
|
||||
builder: ((context, cubit, status) {
|
||||
return status.isSubmissionInProgress
|
||||
? const CircularProgressIndicator()
|
||||
: ElevatedButton(
|
||||
onPressed: status.isValidated ? () => cubit.submit() : null,
|
||||
child: const Text('Edit profile'),
|
||||
);
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class EditProfileForm extends StatelessWidget {
|
||||
const EditProfileForm({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocListener<EditProfileCubit, FormDataState>(
|
||||
listener: (context, state) {
|
||||
if (state.status == FormStatus.submissionFailure) {
|
||||
ScaffoldMessenger.of(context)
|
||||
..hideCurrentSnackBar()
|
||||
..showSnackBar(
|
||||
SnackBar(content: Text(state.errorMessage ?? 'Edit Failure')),
|
||||
);
|
||||
}
|
||||
},
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
_EmailInput(),
|
||||
const SizedBox(height: 8),
|
||||
_OldPasswordInput(),
|
||||
const SizedBox(height: 8),
|
||||
_NewPasswordInput(),
|
||||
const SizedBox(height: 16),
|
||||
_EditButton(),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
+27
-13
@@ -1,12 +1,20 @@
|
||||
// Author: Hugo Pointcheval
|
||||
// Email: git@pcl.ovh
|
||||
// -----
|
||||
// File: home_page.dart
|
||||
// Created Date: 19/08/2022 14:38:24
|
||||
// Last Modified: Wed Nov 09 2022
|
||||
// -----
|
||||
// Copyright (c) 2022
|
||||
// Copyright (C) 2022 WYATT GROUP
|
||||
// Please see the AUTHORS file for details.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import 'package:example_router/presentation/features/edit_profile/edit_profile_page.dart';
|
||||
import 'package:example_router/presentation/features/sub/sub_page.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
@@ -25,7 +33,8 @@ class HomePage extends StatelessWidget {
|
||||
title: const Text('Home'),
|
||||
actions: [
|
||||
IconButton(
|
||||
onPressed: () => context.read<AuthenticationCubit<int>>().signOut(),
|
||||
onPressed: () =>
|
||||
context.read<AuthenticationCubit<int>>().signOut(),
|
||||
icon: const Icon(Icons.logout_rounded))
|
||||
],
|
||||
),
|
||||
@@ -35,8 +44,8 @@ class HomePage extends StatelessWidget {
|
||||
child: Column(
|
||||
children: [
|
||||
AuthenticationBuilder<int>(
|
||||
authenticated: (context, accountWrapper) =>
|
||||
Text('Logged as ${accountWrapper.account?.email} | GeneratedId is ${accountWrapper.data}'),
|
||||
authenticated: (context, accountWrapper) => Text(
|
||||
'Logged as ${accountWrapper.account?.email} | GeneratedId is ${accountWrapper.data}'),
|
||||
unauthenticated: (context) =>
|
||||
const Text('Not logged (unauthenticated)'),
|
||||
unknown: (context) => const Text('Not logged (unknown)'),
|
||||
@@ -45,8 +54,13 @@ class HomePage extends StatelessWidget {
|
||||
height: 8,
|
||||
),
|
||||
ElevatedButton(
|
||||
onPressed: () => context.pushNamed(SubPage.pageName),
|
||||
child: const Text('Go to sub page')),
|
||||
onPressed: () => context.pushNamed(SubPage.pageName),
|
||||
child: const Text('Go to sub page'),
|
||||
),
|
||||
ElevatedButton(
|
||||
onPressed: () => context.pushNamed(EditProfilePage.pageName),
|
||||
child: const Text('Go to edit profile page'),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
+15
-8
@@ -1,11 +1,18 @@
|
||||
// Author: Hugo Pointcheval
|
||||
// Email: git@pcl.ovh
|
||||
// -----
|
||||
// File: sign_in_page.dart
|
||||
// Created Date: 19/08/2022 12:41:42
|
||||
// Last Modified: 19/08/2022 15:26:36
|
||||
// -----
|
||||
// Copyright (c) 2022
|
||||
// Copyright (C) 2022 WYATT GROUP
|
||||
// Please see the AUTHORS file for details.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import 'package:example_router/presentation/features/sign_in/widgets/sign_in_form.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
+33
-8
@@ -1,11 +1,18 @@
|
||||
// Author: Hugo Pointcheval
|
||||
// Email: git@pcl.ovh
|
||||
// -----
|
||||
// File: sign_in_form.dart
|
||||
// Created Date: 19/08/2022 15:24:37
|
||||
// Last Modified: Sat Dec 03 2022
|
||||
// -----
|
||||
// Copyright (c) 2022
|
||||
// Copyright (C) 2022 WYATT GROUP
|
||||
// Please see the AUTHORS file for details.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import 'package:example_router/core/utils/custom_password.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
@@ -87,6 +94,22 @@ class _SignInAnonymouslyButton extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
|
||||
class _SignInWithGoogleButton extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SubmitBuilder<SignInCubit<int>>(
|
||||
builder: ((context, cubit, status) {
|
||||
return status.isSubmissionInProgress
|
||||
? const CircularProgressIndicator()
|
||||
: ElevatedButton(
|
||||
onPressed: () => cubit.signInWithGoogle(),
|
||||
child: const Text('Sign in Google'),
|
||||
);
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class SignInForm extends StatelessWidget {
|
||||
const SignInForm({Key? key}) : super(key: key);
|
||||
|
||||
@@ -109,6 +132,8 @@ class SignInForm extends StatelessWidget {
|
||||
_SignInButton(),
|
||||
const SizedBox(height: 16),
|
||||
_SignInAnonymouslyButton(),
|
||||
const SizedBox(height: 16),
|
||||
_SignInWithGoogleButton(),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
+15
-8
@@ -1,11 +1,18 @@
|
||||
// Author: Hugo Pointcheval
|
||||
// Email: git@pcl.ovh
|
||||
// -----
|
||||
// File: sign_up_page.dart
|
||||
// Created Date: 19/08/2022 12:41:27
|
||||
// Last Modified: 19/08/2022 14:58:51
|
||||
// -----
|
||||
// Copyright (c) 2022
|
||||
// Copyright (C) 2022 WYATT GROUP
|
||||
// Please see the AUTHORS file for details.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import 'package:example_router/presentation/features/sign_up/widgets/sign_up_form.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
+15
-8
@@ -1,11 +1,18 @@
|
||||
// Author: Hugo Pointcheval
|
||||
// Email: git@pcl.ovh
|
||||
// -----
|
||||
// File: sign_up_form.dart
|
||||
// Created Date: 19/08/2022 14:41:08
|
||||
// Last Modified: Sat Dec 03 2022
|
||||
// -----
|
||||
// Copyright (c) 2022
|
||||
// Copyright (C) 2022 WYATT GROUP
|
||||
// Please see the AUTHORS file for details.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import 'package:example_router/core/constants/form_field.dart';
|
||||
import 'package:example_router/core/utils/custom_password.dart';
|
||||
|
||||
+22
-10
@@ -1,11 +1,18 @@
|
||||
// Author: Hugo Pointcheval
|
||||
// Email: git@pcl.ovh
|
||||
// -----
|
||||
// File: sub_page.dart
|
||||
// Created Date: 19/08/2022 16:10:05
|
||||
// Last Modified: Wed Nov 09 2022
|
||||
// -----
|
||||
// Copyright (c) 2022
|
||||
// Copyright (C) 2022 WYATT GROUP
|
||||
// Please see the AUTHORS file for details.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
@@ -23,8 +30,13 @@ class SubPage extends StatelessWidget {
|
||||
title: const Text('Sub'),
|
||||
actions: [
|
||||
IconButton(
|
||||
onPressed: () => context.read<AuthenticationCubit<int>>().signOut(),
|
||||
icon: const Icon(Icons.logout_rounded))
|
||||
onPressed: () =>
|
||||
context.read<AuthenticationCubit<int>>().signOut(),
|
||||
icon: const Icon(Icons.logout_rounded)),
|
||||
IconButton(
|
||||
onPressed: () =>
|
||||
context.read<AuthenticationRepository<int>>().refresh(),
|
||||
icon: const Icon(Icons.refresh))
|
||||
],
|
||||
),
|
||||
body: const Padding(
|
||||
|
||||
+15
-8
@@ -1,11 +1,18 @@
|
||||
// Author: Hugo Pointcheval
|
||||
// Email: git@pcl.ovh
|
||||
// -----
|
||||
// File: welcome_page.dart
|
||||
// Created Date: 19/08/2022 12:33:21
|
||||
// Last Modified: Wed Nov 09 2022
|
||||
// -----
|
||||
// Copyright (c) 2022
|
||||
// Copyright (C) 2022 WYATT GROUP
|
||||
// Please see the AUTHORS file for details.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import 'package:example_router/presentation/features/sign_in/sign_in_page.dart';
|
||||
import 'package:example_router/presentation/features/sign_up/sign_up_page.dart';
|
||||
|
||||
@@ -18,4 +18,3 @@ export 'constants/form_field.dart';
|
||||
export 'constants/form_name.dart';
|
||||
export 'enums/enums.dart';
|
||||
export 'exceptions/exceptions.dart';
|
||||
export 'utils/utils.dart';
|
||||
|
||||
@@ -20,15 +20,14 @@ part 'exceptions_firebase.dart';
|
||||
|
||||
abstract class AuthenticationFailureInterface extends AppException
|
||||
implements Exception {
|
||||
AuthenticationFailureInterface(this.code, this.msg);
|
||||
AuthenticationFailureInterface.fromCode(this.code)
|
||||
: msg = 'An unknown error occurred.';
|
||||
String code;
|
||||
String msg;
|
||||
|
||||
@override
|
||||
String get message => msg;
|
||||
|
||||
AuthenticationFailureInterface(this.code, this.msg);
|
||||
AuthenticationFailureInterface.fromCode(this.code)
|
||||
: msg = 'An unknown error occurred.';
|
||||
}
|
||||
|
||||
/// {@template apply_action_code_failure}
|
||||
@@ -256,3 +255,31 @@ abstract class GetIdTokenFailureInterface
|
||||
|
||||
GetIdTokenFailureInterface.fromCode(super.code) : super.fromCode();
|
||||
}
|
||||
|
||||
abstract class ReauthenticateFailureInterface
|
||||
extends AuthenticationFailureInterface {
|
||||
ReauthenticateFailureInterface(super.code, super.msg);
|
||||
|
||||
ReauthenticateFailureInterface.fromCode(super.code) : super.fromCode();
|
||||
}
|
||||
|
||||
abstract class UpdateEmailFailureInterface
|
||||
extends AuthenticationFailureInterface {
|
||||
UpdateEmailFailureInterface(super.code, super.msg);
|
||||
|
||||
UpdateEmailFailureInterface.fromCode(super.code) : super.fromCode();
|
||||
}
|
||||
|
||||
abstract class UpdatePasswordFailureInterface
|
||||
extends AuthenticationFailureInterface {
|
||||
UpdatePasswordFailureInterface(super.code, super.msg);
|
||||
|
||||
UpdatePasswordFailureInterface.fromCode(super.code) : super.fromCode();
|
||||
}
|
||||
|
||||
abstract class ModelParsingFailureInterface
|
||||
extends AuthenticationFailureInterface {
|
||||
ModelParsingFailureInterface(super.code, super.msg);
|
||||
|
||||
ModelParsingFailureInterface.fromCode(super.code) : super.fromCode();
|
||||
}
|
||||
|
||||
@@ -277,3 +277,82 @@ class GetIdTokenFailureFirebase extends GetIdTokenFailureInterface {
|
||||
|
||||
GetIdTokenFailureFirebase.fromCode(super.code) : super.fromCode();
|
||||
}
|
||||
|
||||
class ReauthenticateFailureFirebase extends ReauthenticateFailureInterface {
|
||||
ReauthenticateFailureFirebase([String? code, String? msg])
|
||||
: super(code ?? 'unknown', msg ?? 'An unknown error occurred.');
|
||||
ReauthenticateFailureFirebase.fromCode(String code) : super.fromCode(code) {
|
||||
switch (code) {
|
||||
case 'user-mismatch':
|
||||
msg = 'Given credential does not correspond to the user.';
|
||||
break;
|
||||
case 'user-not-found':
|
||||
msg = 'User is not found, please create an account.';
|
||||
break;
|
||||
case 'invalid-credential':
|
||||
msg = 'The credential received is malformed or has expired.';
|
||||
break;
|
||||
case 'invalid-email':
|
||||
msg = 'Email is not valid or badly formatted.';
|
||||
break;
|
||||
case 'wrong-password':
|
||||
msg = 'Incorrect password, please try again.';
|
||||
break;
|
||||
case 'invalid-verification-code':
|
||||
msg = 'The credential verification code received is invalid.';
|
||||
break;
|
||||
case 'invalid-verification-id':
|
||||
msg = 'The credential verification ID received is invalid.';
|
||||
break;
|
||||
default:
|
||||
this.code = 'unknown';
|
||||
msg = 'An unknown error occurred.';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class UpdateEmailFailureFirebase extends UpdateEmailFailureInterface {
|
||||
UpdateEmailFailureFirebase([String? code, String? msg])
|
||||
: super(code ?? 'unknown', msg ?? 'An unknown error occurred.');
|
||||
UpdateEmailFailureFirebase.fromCode(String code) : super.fromCode(code) {
|
||||
switch (code) {
|
||||
case 'invalid-email':
|
||||
msg = 'Email is not valid or badly formatted.';
|
||||
break;
|
||||
case 'email-already-in-use':
|
||||
msg = 'An account already exists for that email.';
|
||||
break;
|
||||
case 'requires-recent-login':
|
||||
msg = "User's last sign-in time does not meet the security threshold.";
|
||||
break;
|
||||
default:
|
||||
this.code = 'unknown';
|
||||
msg = 'An unknown error occurred.';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class UpdatePasswordFailureFirebase extends UpdatePasswordFailureInterface {
|
||||
UpdatePasswordFailureFirebase([String? code, String? msg])
|
||||
: super(code ?? 'unknown', msg ?? 'An unknown error occurred.');
|
||||
UpdatePasswordFailureFirebase.fromCode(String code) : super.fromCode(code) {
|
||||
switch (code) {
|
||||
case 'weak-password':
|
||||
msg = 'Please enter a stronger password.';
|
||||
break;
|
||||
case 'requires-recent-login':
|
||||
msg = "User's last sign-in time does not meet the security threshold.";
|
||||
break;
|
||||
default:
|
||||
this.code = 'unknown';
|
||||
msg = 'An unknown error occurred.';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ModelParsingFailureFirebase extends ModelParsingFailureInterface {
|
||||
ModelParsingFailureFirebase([String? code, String? msg])
|
||||
: super(code ?? 'unknown', msg ?? 'An unknown error occurred.');
|
||||
|
||||
ModelParsingFailureFirebase.fromCode(super.code) : super.fromCode();
|
||||
}
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
// Copyright (C) 2022 WYATT GROUP
|
||||
// Please see the AUTHORS file for details.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import 'dart:convert';
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:crypto/crypto.dart';
|
||||
|
||||
class Cryptography {
|
||||
/// Generates a cryptographically secure random nonce, to be included in a
|
||||
/// credential request.
|
||||
static String generateNonce([int length = 32]) {
|
||||
const charset =
|
||||
'0123456789ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvwxyz-._';
|
||||
final random = Random.secure();
|
||||
return List.generate(length, (_) => charset[random.nextInt(charset.length)])
|
||||
.join();
|
||||
}
|
||||
|
||||
/// Returns the sha256 hash of [input] in hex notation.
|
||||
static String sha256ofString(String input) {
|
||||
final bytes = utf8.encode(input);
|
||||
final digest = sha256.convert(bytes);
|
||||
return digest.toString();
|
||||
}
|
||||
}
|
||||
+1
-2
@@ -20,11 +20,10 @@ import 'package:wyatt_type_utils/wyatt_type_utils.dart';
|
||||
|
||||
class AuthenticationCacheDataSourceImpl<T extends Object>
|
||||
extends AuthenticationCacheDataSource<T> {
|
||||
AuthenticationCacheDataSourceImpl();
|
||||
Account? _account;
|
||||
T? _data;
|
||||
|
||||
AuthenticationCacheDataSourceImpl();
|
||||
|
||||
@override
|
||||
Future<void> storeAccount(Account? account) async {
|
||||
_account = account;
|
||||
|
||||
+94
-37
@@ -14,32 +14,21 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import 'package:firebase_auth/firebase_auth.dart';
|
||||
import 'package:wyatt_authentication_bloc/src/data/models/account_model_firebase.dart';
|
||||
import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart';
|
||||
import 'package:wyatt_type_utils/wyatt_type_utils.dart';
|
||||
|
||||
class AuthenticationFirebaseDataSourceImpl
|
||||
extends AuthenticationRemoteDataSource {
|
||||
AuthenticationFirebaseDataSourceImpl({
|
||||
FirebaseAuth? firebaseAuth,
|
||||
GoogleSignIn? googleSignIn,
|
||||
}) : _firebaseAuth = firebaseAuth ?? FirebaseAuth.instance,
|
||||
_googleSignIn = googleSignIn ?? GoogleSignIn();
|
||||
|
||||
final FirebaseAuth _firebaseAuth;
|
||||
|
||||
AuthenticationFirebaseDataSourceImpl({FirebaseAuth? firebaseAuth})
|
||||
: _firebaseAuth = firebaseAuth ?? FirebaseAuth.instance;
|
||||
|
||||
Account _mapper(User user) => AccountModel(
|
||||
uid: user.uid,
|
||||
emailVerified: user.emailVerified,
|
||||
isAnonymous: user.isAnonymous,
|
||||
providerId: user.providerData.first.providerId,
|
||||
creationTime: user.metadata.creationTime,
|
||||
lastSignInTime: user.metadata.lastSignInTime,
|
||||
isNewUser: (user.metadata.creationTime != null &&
|
||||
user.metadata.lastSignInTime != null)
|
||||
? user.metadata.lastSignInTime! == user.metadata.creationTime!
|
||||
: null,
|
||||
email: user.email,
|
||||
phoneNumber: user.phoneNumber,
|
||||
photoURL: user.photoURL,
|
||||
);
|
||||
final GoogleSignIn _googleSignIn;
|
||||
UserCredential? _latestCreds;
|
||||
|
||||
@override
|
||||
Future<Account> signInWithEmailAndPassword({
|
||||
@@ -51,12 +40,9 @@ class AuthenticationFirebaseDataSourceImpl
|
||||
email: email,
|
||||
password: password,
|
||||
);
|
||||
_latestCreds = userCredential;
|
||||
final user = userCredential.user;
|
||||
if (user.isNotNull) {
|
||||
return _mapper(user!);
|
||||
} else {
|
||||
throw Exception(); // Get caught just after.
|
||||
}
|
||||
return AccountModelFirebase.fromFirebaseUser(user);
|
||||
} on FirebaseAuthException catch (e) {
|
||||
throw SignInWithEmailAndPasswordFailureFirebase.fromCode(e.code);
|
||||
} catch (_) {
|
||||
@@ -76,12 +62,9 @@ class AuthenticationFirebaseDataSourceImpl
|
||||
email: email,
|
||||
password: password,
|
||||
);
|
||||
_latestCreds = userCredential;
|
||||
final user = userCredential.user;
|
||||
if (user.isNotNull) {
|
||||
return _mapper(user!);
|
||||
} else {
|
||||
throw Exception(); // Get caught just after.
|
||||
}
|
||||
return AccountModelFirebase.fromFirebaseUser(user);
|
||||
} on FirebaseAuthException catch (e) {
|
||||
throw SignUpWithEmailAndPasswordFailureFirebase.fromCode(e.code);
|
||||
} catch (_) {
|
||||
@@ -92,6 +75,7 @@ class AuthenticationFirebaseDataSourceImpl
|
||||
@override
|
||||
Future<void> signOut() async {
|
||||
try {
|
||||
_latestCreds = null;
|
||||
await _firebaseAuth.signOut();
|
||||
} catch (_) {
|
||||
throw SignOutFailureFirebase();
|
||||
@@ -117,8 +101,11 @@ class AuthenticationFirebaseDataSourceImpl
|
||||
@override
|
||||
Stream<Account?> streamAccount() =>
|
||||
_firebaseAuth.userChanges().map<Account?>((user) {
|
||||
final Account? account = (user.isNotNull) ? _mapper(user!) : null;
|
||||
return account;
|
||||
try {
|
||||
return AccountModelFirebase.fromFirebaseUser(user);
|
||||
} on FirebaseAuthException {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
@override
|
||||
@@ -164,12 +151,9 @@ class AuthenticationFirebaseDataSourceImpl
|
||||
Future<Account> signInAnonymously() async {
|
||||
try {
|
||||
final userCredential = await _firebaseAuth.signInAnonymously();
|
||||
_latestCreds = userCredential;
|
||||
final user = userCredential.user;
|
||||
if (user.isNotNull) {
|
||||
return _mapper(user!);
|
||||
} else {
|
||||
throw Exception(); // Get caught just after.
|
||||
}
|
||||
return AccountModelFirebase.fromFirebaseUser(user);
|
||||
} on FirebaseAuthException catch (e) {
|
||||
throw SignInAnonymouslyFailureFirebase.fromCode(e.code);
|
||||
} catch (_) {
|
||||
@@ -177,6 +161,35 @@ class AuthenticationFirebaseDataSourceImpl
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Account> signInWithGoogle() async {
|
||||
try {
|
||||
// Trigger the authentication flow
|
||||
final GoogleSignInAccount? googleUser = await _googleSignIn.signIn();
|
||||
|
||||
// Obtain the auth details from the request
|
||||
final GoogleSignInAuthentication? googleAuth =
|
||||
await googleUser?.authentication;
|
||||
|
||||
// Create a new credential
|
||||
final credential = GoogleAuthProvider.credential(
|
||||
accessToken: googleAuth?.accessToken,
|
||||
idToken: googleAuth?.idToken,
|
||||
);
|
||||
|
||||
final userCredential =
|
||||
await _firebaseAuth.signInWithCredential(credential);
|
||||
|
||||
_latestCreds = userCredential;
|
||||
final user = userCredential.user;
|
||||
return AccountModelFirebase.fromFirebaseUser(user);
|
||||
} on FirebaseAuthException catch (e) {
|
||||
throw SignInWithGoogleFailureFirebase.fromCode(e.code);
|
||||
} catch (_) {
|
||||
throw SignInWithGoogleFailureFirebase();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<bool> verifyPasswordResetCode({required String code}) async {
|
||||
try {
|
||||
@@ -199,4 +212,48 @@ class AuthenticationFirebaseDataSourceImpl
|
||||
throw RefreshFailureFirebase();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Account> reauthenticateWithCredential() async {
|
||||
try {
|
||||
if (_latestCreds?.credential != null) {
|
||||
await _firebaseAuth.currentUser
|
||||
?.reauthenticateWithCredential(_latestCreds!.credential!);
|
||||
} else {
|
||||
throw Exception(); // Get caught just after.
|
||||
}
|
||||
final user = _firebaseAuth.currentUser;
|
||||
return AccountModelFirebase.fromFirebaseUser(user);
|
||||
} on FirebaseAuthException catch (e) {
|
||||
throw ReauthenticateFailureFirebase.fromCode(e.code);
|
||||
} catch (_) {
|
||||
throw ReauthenticateFailureFirebase();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Account> updateEmail({required String email}) async {
|
||||
try {
|
||||
await _firebaseAuth.currentUser!.updateEmail(email);
|
||||
final user = _firebaseAuth.currentUser;
|
||||
return AccountModelFirebase.fromFirebaseUser(user);
|
||||
} on FirebaseAuthException catch (e) {
|
||||
throw UpdateEmailFailureFirebase.fromCode(e.code);
|
||||
} catch (_) {
|
||||
throw UpdateEmailFailureFirebase();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Account> updatePassword({required String password}) async {
|
||||
try {
|
||||
await _firebaseAuth.currentUser!.updatePassword(password);
|
||||
final user = _firebaseAuth.currentUser;
|
||||
return AccountModelFirebase.fromFirebaseUser(user);
|
||||
} on FirebaseAuthException catch (e) {
|
||||
throw UpdatePasswordFailureFirebase.fromCode(e.code);
|
||||
} catch (_) {
|
||||
throw UpdatePasswordFailureFirebase();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+70
-6
@@ -21,19 +21,19 @@ import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart';
|
||||
import 'package:wyatt_type_utils/wyatt_type_utils.dart';
|
||||
|
||||
class AuthenticationMockDataSourceImpl extends AuthenticationRemoteDataSource {
|
||||
AuthenticationMockDataSourceImpl({
|
||||
this.idToken = 'fake-id-token',
|
||||
this.registeredAccounts,
|
||||
});
|
||||
Pair<Account, String>? _connectedMock;
|
||||
Pair<Account, String>? _registeredMock;
|
||||
DateTime _lastSignInTime = DateTime.now();
|
||||
final StreamController<Account?> _streamAccount = StreamController()
|
||||
..add(null);
|
||||
|
||||
final List<Pair<Account, String>>? registeredAccounts;
|
||||
final String idToken;
|
||||
|
||||
AuthenticationMockDataSourceImpl({
|
||||
this.idToken = 'fake-id-token',
|
||||
this.registeredAccounts,
|
||||
});
|
||||
|
||||
Future<void> _randomDelay() async {
|
||||
await Future<void>.delayed(
|
||||
Duration(milliseconds: Random().nextInt(400) + 200),
|
||||
@@ -111,13 +111,33 @@ class AuthenticationMockDataSourceImpl extends AuthenticationRemoteDataSource {
|
||||
uid: 'mock-id-anom',
|
||||
emailVerified: false,
|
||||
isAnonymous: true,
|
||||
providerId: 'wyatt',
|
||||
providerId: 'wyatt-studio.fr',
|
||||
creationTime: creation,
|
||||
lastSignInTime: creation,
|
||||
isNewUser: creation == creation,
|
||||
);
|
||||
_streamAccount.add(mock);
|
||||
_connectedMock = _connectedMock?.copyWith(left: mock);
|
||||
_lastSignInTime = DateTime.now();
|
||||
return Future.value(mock);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Account> signInWithGoogle() async {
|
||||
await _randomDelay();
|
||||
final creation = DateTime.now();
|
||||
final mock = AccountModel(
|
||||
uid: 'mock-id-google',
|
||||
emailVerified: true,
|
||||
isAnonymous: false,
|
||||
providerId: 'google.com',
|
||||
creationTime: creation,
|
||||
lastSignInTime: creation,
|
||||
isNewUser: creation == creation,
|
||||
);
|
||||
_streamAccount.add(mock);
|
||||
_connectedMock = _connectedMock?.copyWith(left: mock);
|
||||
_lastSignInTime = DateTime.now();
|
||||
return Future.value(mock);
|
||||
}
|
||||
|
||||
@@ -149,6 +169,7 @@ class AuthenticationMockDataSourceImpl extends AuthenticationRemoteDataSource {
|
||||
}
|
||||
_streamAccount.add(_registeredMock!.left);
|
||||
_connectedMock = _registeredMock!.copyWith();
|
||||
_lastSignInTime = DateTime.now();
|
||||
return _registeredMock!.left!;
|
||||
}
|
||||
throw SignInWithCredentialFailureFirebase();
|
||||
@@ -193,6 +214,8 @@ class AuthenticationMockDataSourceImpl extends AuthenticationRemoteDataSource {
|
||||
);
|
||||
_streamAccount.add(mock);
|
||||
_registeredMock = Pair(mock, password);
|
||||
_connectedMock = _registeredMock!.copyWith();
|
||||
_lastSignInTime = DateTime.now();
|
||||
return Future.value(mock);
|
||||
}
|
||||
|
||||
@@ -204,4 +227,45 @@ class AuthenticationMockDataSourceImpl extends AuthenticationRemoteDataSource {
|
||||
await _randomDelay();
|
||||
return true;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Account> reauthenticateWithCredential() async {
|
||||
await _randomDelay();
|
||||
if (_connectedMock.isNull) {
|
||||
throw ReauthenticateFailureFirebase();
|
||||
}
|
||||
await refresh();
|
||||
_lastSignInTime = DateTime.now();
|
||||
return Future.value(_connectedMock?.left);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Account> updateEmail({required String email}) {
|
||||
final before = DateTime.now().subtract(const Duration(seconds: 10));
|
||||
if (_lastSignInTime.isBefore(before)) {
|
||||
throw UpdateEmailFailureFirebase('requires-recent-login');
|
||||
}
|
||||
final refresh = DateTime.now();
|
||||
final mock = (_connectedMock?.left as AccountModel?)
|
||||
?.copyWith(lastSignInTime: refresh, email: email);
|
||||
_connectedMock = _connectedMock?.copyWith(left: mock);
|
||||
_registeredMock = _registeredMock?.copyWith(left: mock);
|
||||
_streamAccount.add(mock);
|
||||
return Future.value(_connectedMock?.left);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Account> updatePassword({required String password}) {
|
||||
final before = DateTime.now().subtract(const Duration(seconds: 10));
|
||||
if (_lastSignInTime.isBefore(before)) {
|
||||
throw UpdatePasswordFailureFirebase('requires-recent-login');
|
||||
}
|
||||
final refresh = DateTime.now();
|
||||
final mock = (_connectedMock?.left as AccountModel?)
|
||||
?.copyWith(lastSignInTime: refresh);
|
||||
_connectedMock = _connectedMock?.copyWith(left: mock, right: password);
|
||||
_registeredMock = _registeredMock?.copyWith(left: mock, right: password);
|
||||
_streamAccount.add(mock);
|
||||
return Future.value(_connectedMock?.left);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,16 +72,17 @@ class AccountModel extends Account {
|
||||
String? phoneNumber,
|
||||
String? photoURL,
|
||||
String? providerId,
|
||||
}) => AccountModel(
|
||||
uid: uid ?? this.uid,
|
||||
email: email ?? this.email,
|
||||
creationTime: creationTime ?? this.creationTime,
|
||||
emailVerified: emailVerified ?? this.emailVerified,
|
||||
isAnonymous: isAnonymous ?? this.isAnonymous,
|
||||
isNewUser: isNewUser ?? this.isNewUser,
|
||||
lastSignInTime: lastSignInTime ?? this.lastSignInTime,
|
||||
phoneNumber: phoneNumber ?? this.phoneNumber,
|
||||
photoURL: photoURL ?? this.photoURL,
|
||||
providerId: providerId ?? this.providerId,
|
||||
);
|
||||
}) =>
|
||||
AccountModel(
|
||||
uid: uid ?? this.uid,
|
||||
email: email ?? this.email,
|
||||
creationTime: creationTime ?? this.creationTime,
|
||||
emailVerified: emailVerified ?? this.emailVerified,
|
||||
isAnonymous: isAnonymous ?? this.isAnonymous,
|
||||
isNewUser: isNewUser ?? this.isNewUser,
|
||||
lastSignInTime: lastSignInTime ?? this.lastSignInTime,
|
||||
phoneNumber: phoneNumber ?? this.phoneNumber,
|
||||
photoURL: photoURL ?? this.photoURL,
|
||||
providerId: providerId ?? this.providerId,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
// ignore_for_file: public_member_api_docs, sort_constructors_first
|
||||
// Copyright (C) 2022 WYATT GROUP
|
||||
// Please see the AUTHORS file for details.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart';
|
||||
|
||||
class AccountModelFirebase extends AccountModel {
|
||||
AccountModelFirebase._({
|
||||
required super.uid,
|
||||
required super.emailVerified,
|
||||
required super.isAnonymous,
|
||||
required super.providerId,
|
||||
super.lastSignInTime,
|
||||
super.creationTime,
|
||||
super.isNewUser,
|
||||
super.email,
|
||||
super.phoneNumber,
|
||||
super.photoURL,
|
||||
});
|
||||
|
||||
factory AccountModelFirebase.fromFirebaseUser(User? user) {
|
||||
if (user != null) {
|
||||
return AccountModelFirebase._(
|
||||
uid: user.uid,
|
||||
emailVerified: user.emailVerified,
|
||||
isAnonymous: user.isAnonymous,
|
||||
providerId: user.providerData.first.providerId,
|
||||
creationTime: user.metadata.creationTime,
|
||||
lastSignInTime: user.metadata.lastSignInTime,
|
||||
isNewUser: (user.metadata.creationTime != null &&
|
||||
user.metadata.lastSignInTime != null)
|
||||
? user.metadata.lastSignInTime! == user.metadata.creationTime!
|
||||
: null,
|
||||
email: user.email,
|
||||
phoneNumber: user.phoneNumber,
|
||||
photoURL: user.photoURL,
|
||||
);
|
||||
} else {
|
||||
throw ModelParsingFailureFirebase('null-user', 'User cannot be null!');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -29,8 +29,9 @@ class AccountWrapperModel<T> extends AccountWrapper<T> {
|
||||
AccountWrapperModel<T> copyWith({
|
||||
Account? account,
|
||||
T? data,
|
||||
}) => AccountWrapperModel<T>(
|
||||
account ?? this.account,
|
||||
data ?? this.data,
|
||||
);
|
||||
}) =>
|
||||
AccountWrapperModel<T>(
|
||||
account ?? this.account,
|
||||
data ?? this.data,
|
||||
);
|
||||
}
|
||||
|
||||
+57
-13
@@ -42,19 +42,6 @@ typedef OnAuthChange<T> = FutureOrResult<T?> Function(
|
||||
|
||||
class AuthenticationRepositoryImpl<T extends Object>
|
||||
extends AuthenticationRepository<T> {
|
||||
final AuthenticationCacheDataSource<T> _authenticationLocalDataSource;
|
||||
final AuthenticationRemoteDataSource _authenticationRemoteDataSource;
|
||||
|
||||
late FormRepository _formRepository;
|
||||
|
||||
final OnSignUpSuccess<T>? _onSignUpSuccess;
|
||||
|
||||
final OnAuthChange<T>? _onAccountChanges;
|
||||
final StreamController<FutureOrResult<AccountWrapper<T>>> _signUpStream =
|
||||
StreamController();
|
||||
|
||||
bool _pause = false; // Semaphore
|
||||
|
||||
AuthenticationRepositoryImpl({
|
||||
required AuthenticationCacheDataSource<T> authenticationCacheDataSource,
|
||||
required AuthenticationRemoteDataSource authenticationRemoteDataSource,
|
||||
@@ -106,6 +93,18 @@ class AuthenticationRepositoryImpl<T extends Object>
|
||||
),
|
||||
);
|
||||
}
|
||||
final AuthenticationCacheDataSource<T> _authenticationLocalDataSource;
|
||||
final AuthenticationRemoteDataSource _authenticationRemoteDataSource;
|
||||
|
||||
late FormRepository _formRepository;
|
||||
|
||||
final OnSignUpSuccess<T>? _onSignUpSuccess;
|
||||
|
||||
final OnAuthChange<T>? _onAccountChanges;
|
||||
final StreamController<FutureOrResult<AccountWrapper<T>>> _signUpStream =
|
||||
StreamController();
|
||||
|
||||
bool _pause = false;
|
||||
|
||||
@override
|
||||
FormRepository get formRepository => _formRepository;
|
||||
@@ -295,6 +294,17 @@ class AuthenticationRepositoryImpl<T extends Object>
|
||||
(error) => error,
|
||||
);
|
||||
|
||||
@override
|
||||
FutureOrResult<Account> signInWithGoogle() =>
|
||||
Result.tryCatchAsync<Account, AppException, AppException>(
|
||||
() async {
|
||||
final account =
|
||||
await _authenticationRemoteDataSource.signInWithGoogle();
|
||||
return account;
|
||||
},
|
||||
(error) => error,
|
||||
);
|
||||
|
||||
@override
|
||||
FutureOrResult<bool> verifyPasswordResetCode({required String code}) =>
|
||||
Result.tryCatchAsync<bool, AppException, AppException>(
|
||||
@@ -314,4 +324,38 @@ class AuthenticationRepositoryImpl<T extends Object>
|
||||
},
|
||||
(error) => error,
|
||||
);
|
||||
|
||||
@override
|
||||
FutureOrResult<Account> reauthenticateWithCredential() =>
|
||||
Result.tryCatchAsync<Account, AppException, AppException>(
|
||||
() async {
|
||||
final account = await _authenticationRemoteDataSource
|
||||
.reauthenticateWithCredential();
|
||||
return account;
|
||||
},
|
||||
(error) => error,
|
||||
);
|
||||
|
||||
@override
|
||||
FutureOrResult<Account> updateEmail({required String email}) =>
|
||||
Result.tryCatchAsync<Account, AppException, AppException>(
|
||||
() async {
|
||||
final account =
|
||||
await _authenticationRemoteDataSource.updateEmail(email: email);
|
||||
return account;
|
||||
},
|
||||
(error) => error,
|
||||
);
|
||||
|
||||
@override
|
||||
FutureOrResult<Account> updatePassword({required String password}) =>
|
||||
Result.tryCatchAsync<Account, AppException, AppException>(
|
||||
() async {
|
||||
final account = await _authenticationRemoteDataSource.updatePassword(
|
||||
password: password,
|
||||
);
|
||||
return account;
|
||||
},
|
||||
(error) => error,
|
||||
);
|
||||
}
|
||||
|
||||
+8
@@ -48,4 +48,12 @@ abstract class AuthenticationRemoteDataSource extends BaseRemoteDataSource {
|
||||
Future<bool> verifyPasswordResetCode({required String code});
|
||||
|
||||
Future<Account> signInAnonymously();
|
||||
|
||||
Future<Account> signInWithGoogle();
|
||||
|
||||
Future<Account> updateEmail({required String email});
|
||||
|
||||
Future<Account> updatePassword({required String password});
|
||||
|
||||
Future<Account> reauthenticateWithCredential();
|
||||
}
|
||||
|
||||
+40
@@ -73,6 +73,13 @@ abstract class AuthenticationRepository<T> extends BaseRepository {
|
||||
/// {@endtemplate}
|
||||
FutureOrResult<Account> signInAnonymously();
|
||||
|
||||
/// {@template signin_google}
|
||||
/// Starts the Sign In with Google Flow.
|
||||
///
|
||||
/// Throws a SignInWithGoogleFailureInterface if an exception occurs.
|
||||
/// {@endtemplate}
|
||||
FutureOrResult<Account> signInWithGoogle();
|
||||
|
||||
/// {@template signin_pwd}
|
||||
/// Signs in with the provided [email] and [password].
|
||||
///
|
||||
@@ -84,12 +91,45 @@ abstract class AuthenticationRepository<T> extends BaseRepository {
|
||||
required String password,
|
||||
});
|
||||
|
||||
/// {@template update_email}
|
||||
/// Update or add [email].
|
||||
///
|
||||
/// Throws a UpdateEmailFailureInterface if
|
||||
/// an exception occurs.
|
||||
/// {@endtemplate}
|
||||
FutureOrResult<Account> updateEmail({
|
||||
required String email,
|
||||
});
|
||||
|
||||
/// {@template update_password}
|
||||
/// Update or add [password].
|
||||
///
|
||||
/// Throws a UpdatePasswordFailureInterface if
|
||||
/// an exception occurs.
|
||||
/// {@endtemplate}
|
||||
FutureOrResult<Account> updatePassword({
|
||||
required String password,
|
||||
});
|
||||
|
||||
/// {@template reauthenticate}
|
||||
/// Some security-sensitive actions—such as deleting an account,
|
||||
/// setting a primary email address, and changing a password—require that
|
||||
/// the user has recently signed in.
|
||||
///
|
||||
/// Throws a ReauthenticateFailureInterface if
|
||||
/// an exception occurs.
|
||||
/// {@endtemplate}
|
||||
FutureOrResult<Account> reauthenticateWithCredential();
|
||||
|
||||
/// {@template signout}
|
||||
/// Signs out the current user.
|
||||
/// It also clears the cache and the associated data.
|
||||
/// {@endtemplate}
|
||||
FutureOrResult<void> signOut();
|
||||
|
||||
/// {@template refresh}
|
||||
/// Refreshes the current user, if signed in.
|
||||
/// {@endtemplate}
|
||||
FutureOrResult<void> refresh();
|
||||
|
||||
/// {@template stream_account}
|
||||
|
||||
+1
-2
@@ -26,14 +26,13 @@ import 'package:wyatt_type_utils/wyatt_type_utils.dart';
|
||||
part 'authentication_state.dart';
|
||||
|
||||
class AuthenticationCubit<Extra> extends Cubit<AuthenticationState<Extra>> {
|
||||
final AuthenticationRepository<Extra> _authenticationRepository;
|
||||
|
||||
AuthenticationCubit({
|
||||
required AuthenticationRepository<Extra> authenticationRepository,
|
||||
}) : _authenticationRepository = authenticationRepository,
|
||||
super(const AuthenticationState.unknown()) {
|
||||
_listenForAuthenticationChanges();
|
||||
}
|
||||
final AuthenticationRepository<Extra> _authenticationRepository;
|
||||
|
||||
void _listenForAuthenticationChanges() {
|
||||
_authenticationRepository.streamAccount().listen((accountFutureResult) {
|
||||
|
||||
+8
-9
@@ -17,13 +17,8 @@
|
||||
part of 'authentication_cubit.dart';
|
||||
|
||||
class AuthenticationState<Extra> extends Equatable {
|
||||
final AuthenticationStatus status;
|
||||
final AccountWrapper<Extra>? accountWrapper;
|
||||
|
||||
const AuthenticationState._({required this.status, this.accountWrapper});
|
||||
|
||||
const AuthenticationState.unknown()
|
||||
: this._(status: AuthenticationStatus.unknown);
|
||||
const AuthenticationState.unauthenticated()
|
||||
: this._(status: AuthenticationStatus.unauthenticated);
|
||||
|
||||
const AuthenticationState.authenticated(AccountWrapper<Extra> accountWrapper)
|
||||
: this._(
|
||||
@@ -31,8 +26,12 @@ class AuthenticationState<Extra> extends Equatable {
|
||||
accountWrapper: accountWrapper,
|
||||
);
|
||||
|
||||
const AuthenticationState.unauthenticated()
|
||||
: this._(status: AuthenticationStatus.unauthenticated);
|
||||
const AuthenticationState.unknown()
|
||||
: this._(status: AuthenticationStatus.unknown);
|
||||
|
||||
const AuthenticationState._({required this.status, this.accountWrapper});
|
||||
final AuthenticationStatus status;
|
||||
final AccountWrapper<Extra>? accountWrapper;
|
||||
|
||||
@override
|
||||
List<Object?> get props => [status, accountWrapper];
|
||||
|
||||
+1
-2
@@ -24,12 +24,11 @@ import 'package:wyatt_form_bloc/wyatt_form_bloc.dart';
|
||||
part 'email_verification_state.dart';
|
||||
|
||||
class EmailVerificationCubit<Extra> extends Cubit<EmailVerificationState> {
|
||||
final AuthenticationRepository<Extra> _authenticationRepository;
|
||||
|
||||
EmailVerificationCubit({
|
||||
required AuthenticationRepository<Extra> authenticationRepository,
|
||||
}) : _authenticationRepository = authenticationRepository,
|
||||
super(const EmailVerificationState());
|
||||
final AuthenticationRepository<Extra> _authenticationRepository;
|
||||
|
||||
FutureOr<void> sendEmailVerification() async {
|
||||
emit(state.copyWith(status: FormStatus.submissionInProgress));
|
||||
|
||||
+3
-4
@@ -25,10 +25,6 @@ import 'package:wyatt_type_utils/wyatt_type_utils.dart';
|
||||
part 'password_reset_state.dart';
|
||||
|
||||
class PasswordResetCubit<Extra> extends FormDataCubit<PasswordResetState> {
|
||||
final AuthenticationRepository<Extra> _authenticationRepository;
|
||||
FormRepository get _formRepository =>
|
||||
_authenticationRepository.formRepository;
|
||||
|
||||
PasswordResetCubit({
|
||||
required AuthenticationRepository<Extra> authenticationRepository,
|
||||
}) : _authenticationRepository = authenticationRepository,
|
||||
@@ -38,6 +34,9 @@ class PasswordResetCubit<Extra> extends FormDataCubit<PasswordResetState> {
|
||||
.accessForm(AuthFormName.passwordResetForm),
|
||||
),
|
||||
);
|
||||
final AuthenticationRepository<Extra> _authenticationRepository;
|
||||
FormRepository get _formRepository =>
|
||||
_authenticationRepository.formRepository;
|
||||
|
||||
@override
|
||||
String get formName => AuthFormName.passwordResetForm;
|
||||
|
||||
+1
-2
@@ -17,13 +17,12 @@
|
||||
part of 'password_reset_cubit.dart';
|
||||
|
||||
class PasswordResetState extends FormDataState {
|
||||
Email get email => form.validatorOf(AuthFormField.email);
|
||||
|
||||
const PasswordResetState({
|
||||
required super.form,
|
||||
super.status = FormStatus.pure,
|
||||
super.errorMessage,
|
||||
});
|
||||
Email get email => form.validatorOf(AuthFormField.email);
|
||||
|
||||
PasswordResetState copyWith({
|
||||
WyattForm? form,
|
||||
|
||||
+23
-4
@@ -23,10 +23,6 @@ import 'package:wyatt_type_utils/wyatt_type_utils.dart';
|
||||
part 'sign_in_state.dart';
|
||||
|
||||
class SignInCubit<Extra> extends FormDataCubit<SignInState> {
|
||||
final AuthenticationRepository<Extra> _authenticationRepository;
|
||||
FormRepository get _formRepository =>
|
||||
_authenticationRepository.formRepository;
|
||||
|
||||
SignInCubit({
|
||||
required AuthenticationRepository<Extra> authenticationRepository,
|
||||
}) : _authenticationRepository = authenticationRepository,
|
||||
@@ -36,6 +32,9 @@ class SignInCubit<Extra> extends FormDataCubit<SignInState> {
|
||||
.accessForm(AuthFormName.signInForm),
|
||||
),
|
||||
);
|
||||
final AuthenticationRepository<Extra> _authenticationRepository;
|
||||
FormRepository get _formRepository =>
|
||||
_authenticationRepository.formRepository;
|
||||
|
||||
@override
|
||||
String get formName => AuthFormName.signInForm;
|
||||
@@ -206,4 +205,24 @@ class SignInCubit<Extra> extends FormDataCubit<SignInState> {
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
FutureOr<void> signInWithGoogle() async {
|
||||
if (state.status.isSubmissionInProgress) {
|
||||
return;
|
||||
}
|
||||
// TODO(wyatt): maybe emit new state (to not carry an old errorMessage)
|
||||
emit(state.copyWith(status: FormStatus.submissionInProgress));
|
||||
|
||||
final uid = await _authenticationRepository.signInWithGoogle();
|
||||
|
||||
emit(
|
||||
uid.fold(
|
||||
(value) => state.copyWith(status: FormStatus.submissionSuccess),
|
||||
(error) => state.copyWith(
|
||||
errorMessage: error.message,
|
||||
status: FormStatus.submissionFailure,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
+4
-5
@@ -17,16 +17,15 @@
|
||||
part of 'sign_in_cubit.dart';
|
||||
|
||||
class SignInState extends FormDataState {
|
||||
FormInputValidator<String?, ValidationError> get email =>
|
||||
form.validatorOf(AuthFormField.email);
|
||||
FormInputValidator<String?, ValidationError> get password =>
|
||||
form.validatorOf(AuthFormField.password);
|
||||
|
||||
const SignInState({
|
||||
required super.form,
|
||||
super.status = FormStatus.pure,
|
||||
super.errorMessage,
|
||||
});
|
||||
FormInputValidator<String?, ValidationError> get email =>
|
||||
form.validatorOf(AuthFormField.email);
|
||||
FormInputValidator<String?, ValidationError> get password =>
|
||||
form.validatorOf(AuthFormField.password);
|
||||
|
||||
SignInState copyWith({
|
||||
WyattForm? form,
|
||||
|
||||
+3
-4
@@ -25,10 +25,6 @@ import 'package:wyatt_type_utils/wyatt_type_utils.dart';
|
||||
part 'sign_up_state.dart';
|
||||
|
||||
class SignUpCubit<Extra> extends FormDataCubit<SignUpState> {
|
||||
final AuthenticationRepository<Extra> _authenticationRepository;
|
||||
FormRepository get _formRepository =>
|
||||
_authenticationRepository.formRepository;
|
||||
|
||||
SignUpCubit({
|
||||
required AuthenticationRepository<Extra> authenticationRepository,
|
||||
}) : _authenticationRepository = authenticationRepository,
|
||||
@@ -38,6 +34,9 @@ class SignUpCubit<Extra> extends FormDataCubit<SignUpState> {
|
||||
.accessForm(AuthFormName.signUpForm),
|
||||
),
|
||||
);
|
||||
final AuthenticationRepository<Extra> _authenticationRepository;
|
||||
FormRepository get _formRepository =>
|
||||
_authenticationRepository.formRepository;
|
||||
|
||||
@override
|
||||
String get formName => AuthFormName.signUpForm;
|
||||
|
||||
+4
-5
@@ -17,16 +17,15 @@
|
||||
part of 'sign_up_cubit.dart';
|
||||
|
||||
class SignUpState extends FormDataState {
|
||||
FormInputValidator<String?, ValidationError> get email =>
|
||||
form.validatorOf(AuthFormField.email);
|
||||
FormInputValidator<String?, ValidationError> get password =>
|
||||
form.validatorOf(AuthFormField.password);
|
||||
|
||||
const SignUpState({
|
||||
required super.form,
|
||||
super.status = FormStatus.pure,
|
||||
super.errorMessage,
|
||||
});
|
||||
FormInputValidator<String?, ValidationError> get email =>
|
||||
form.validatorOf(AuthFormField.email);
|
||||
FormInputValidator<String?, ValidationError> get password =>
|
||||
form.validatorOf(AuthFormField.password);
|
||||
|
||||
SignUpState copyWith({
|
||||
WyattForm? form,
|
||||
|
||||
@@ -17,4 +17,7 @@
|
||||
/// An authentication library for BLoC.
|
||||
library wyatt_authentication_bloc;
|
||||
|
||||
export 'package:firebase_auth/firebase_auth.dart';
|
||||
export 'package:google_sign_in/google_sign_in.dart';
|
||||
|
||||
export 'src/src.dart';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
name: wyatt_authentication_bloc
|
||||
description: Authentication BLoC for Flutter
|
||||
repository: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages/src/branch/master/packages/wyatt_authentication_bloc
|
||||
version: 0.4.0+3
|
||||
version: 0.4.1
|
||||
|
||||
publish_to: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub
|
||||
|
||||
@@ -10,17 +10,12 @@ environment:
|
||||
flutter: ">=1.17.0"
|
||||
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
|
||||
flutter: { sdk: flutter }
|
||||
crypto: ^3.0.2
|
||||
flutter_bloc: ^8.1.1
|
||||
equatable: ^2.0.5
|
||||
firebase_auth: ^4.1.1
|
||||
google_sign_in: ^5.3.0
|
||||
flutter_facebook_auth: ^4.3.0
|
||||
sign_in_with_apple: ^3.3.0
|
||||
twitter_login: ^4.2.3
|
||||
firebase_auth: ^4.2.0
|
||||
google_sign_in: ^5.4.2
|
||||
rxdart: ^0.27.7
|
||||
|
||||
wyatt_form_bloc:
|
||||
@@ -36,11 +31,10 @@ dependencies:
|
||||
version: ^0.0.4
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
flutter_test: { sdk: flutter }
|
||||
bloc_test: ^9.1.0
|
||||
mocktail: ^0.3.0
|
||||
|
||||
wyatt_analysis:
|
||||
hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub/
|
||||
version: 2.2.2
|
||||
version: 2.3.0
|
||||
|
||||
@@ -22,4 +22,4 @@ dev_dependencies:
|
||||
|
||||
wyatt_analysis:
|
||||
hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub
|
||||
version: ^2.2.2
|
||||
version: ^2.3.0
|
||||
@@ -0,0 +1,133 @@
|
||||
# Miscellaneous
|
||||
*.class
|
||||
*.lock
|
||||
*.log
|
||||
*.pyc
|
||||
*.swp
|
||||
.DS_Store
|
||||
.atom/
|
||||
.buildlog/
|
||||
.history
|
||||
.svn/
|
||||
|
||||
# IntelliJ related
|
||||
*.iml
|
||||
*.ipr
|
||||
*.iws
|
||||
.idea/*
|
||||
|
||||
# Visual Studio Code related
|
||||
.classpath
|
||||
.project
|
||||
.settings/
|
||||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
!.vscode/extensions.json
|
||||
|
||||
# Flutter repo-specific
|
||||
/bin/cache/
|
||||
/bin/mingit/
|
||||
/dev/benchmarks/mega_gallery/
|
||||
/dev/bots/.recipe_deps
|
||||
/dev/bots/android_tools/
|
||||
/dev/docs/doc/
|
||||
/dev/docs/flutter.docs.zip
|
||||
/dev/docs/lib/
|
||||
/dev/docs/pubspec.yaml
|
||||
/dev/integration_tests/**/xcuserdata
|
||||
/dev/integration_tests/**/Pods
|
||||
/packages/flutter/coverage/
|
||||
version
|
||||
|
||||
# packages file containing multi-root paths
|
||||
.packages.generated
|
||||
|
||||
# Flutter/Dart/Pub related
|
||||
**/doc/api/
|
||||
**/ios/Flutter/.last_build_id
|
||||
.dart_tool/
|
||||
.flutter-plugins
|
||||
.flutter-plugins-dependencies
|
||||
.packages
|
||||
.pub-cache/
|
||||
.pub/
|
||||
build/
|
||||
flutter_*.png
|
||||
linked_*.ds
|
||||
unlinked.ds
|
||||
unlinked_spec.ds
|
||||
.fvm/
|
||||
|
||||
# Android related
|
||||
**/android/**/gradle-wrapper.jar
|
||||
**/android/.gradle
|
||||
**/android/captures/
|
||||
**/android/gradlew
|
||||
**/android/gradlew.bat
|
||||
**/android/local.properties
|
||||
**/android/**/GeneratedPluginRegistrant.java
|
||||
**/android/key.properties
|
||||
**/android/.idea/
|
||||
*.jks
|
||||
|
||||
# iOS/XCode related
|
||||
**/ios/**/*.mode1v3
|
||||
**/ios/**/*.mode2v3
|
||||
**/ios/**/*.moved-aside
|
||||
**/ios/**/*.pbxuser
|
||||
**/ios/**/*.perspectivev3
|
||||
**/ios/**/*sync/
|
||||
**/ios/**/.sconsign.dblite
|
||||
**/ios/**/.tags*
|
||||
**/ios/**/.vagrant/
|
||||
**/ios/**/DerivedData/
|
||||
**/ios/**/Icon?
|
||||
**/ios/**/Pods/
|
||||
**/ios/**/.symlinks/
|
||||
**/ios/**/profile
|
||||
**/ios/**/xcuserdata
|
||||
**/ios/.generated/
|
||||
**/ios/Flutter/App.framework
|
||||
**/ios/Flutter/Flutter.framework
|
||||
**/ios/Flutter/Flutter.podspec
|
||||
**/ios/Flutter/Generated.xcconfig
|
||||
**/ios/Flutter/app.flx
|
||||
**/ios/Flutter/app.zip
|
||||
**/ios/Flutter/.last_build_id
|
||||
**/ios/Flutter/flutter_assets/
|
||||
**/ios/Flutter/flutter_export_environment.sh
|
||||
**/ios/ServiceDefinitions.json
|
||||
**/ios/Runner/GeneratedPluginRegistrant.*
|
||||
|
||||
# Coverage
|
||||
coverage/
|
||||
|
||||
# Submodules
|
||||
!pubspec.lock
|
||||
packages/**/pubspec.lock
|
||||
|
||||
# Web related
|
||||
lib/generated_plugin_registrant.dart
|
||||
|
||||
# Symbolication related
|
||||
app.*.symbols
|
||||
|
||||
# Obfuscation related
|
||||
app.*.map.json
|
||||
|
||||
# Exceptions to the above rules.
|
||||
!**/ios/**/default.mode1v3
|
||||
!**/ios/**/default.mode2v3
|
||||
!**/ios/**/default.pbxuser
|
||||
!**/ios/**/default.perspectivev3
|
||||
!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
|
||||
!/dev/ci/**/Gemfile.lock
|
||||
!.vscode/extensions.json
|
||||
!.vscode/launch.json
|
||||
!.idea/codeStyles/
|
||||
!.idea/dictionaries/
|
||||
!.idea/runConfigurations/
|
||||
|
||||
# Omit committing pubspec.lock for library packages; see
|
||||
# https://dart.dev/guides/libraries/private-files#pubspeclock.
|
||||
pubspec.lock
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Launch Example",
|
||||
"request": "launch",
|
||||
"type": "dart",
|
||||
"cwd": "example/",
|
||||
"program": "lib/main.dart",
|
||||
"flutterMode": "debug"
|
||||
},
|
||||
]
|
||||
}
|
||||
Vendored
@@ -4,4 +4,5 @@
|
||||
# Name/Organization <email address>
|
||||
|
||||
Wyatt Group S.A.S
|
||||
Hugo Pointcheval <git@pcl.ovh>
|
||||
Hugo Pointcheval <hugo.pointcheval@wyattapp.io>
|
||||
Malo Léon <malo.leon@wyattapp.io>
|
||||
@@ -0,0 +1,3 @@
|
||||
# 0.0.1
|
||||
|
||||
- TODO: Describe initial release.
|
||||
@@ -1,55 +1,43 @@
|
||||
<!--
|
||||
* Copyright (C) 2022 WYATT GROUP
|
||||
* Please see the AUTHORS file for details.
|
||||
*
|
||||
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
-->
|
||||
|
||||
# Dart - CLI Toolbox
|
||||
|
||||
# Flutter - Wyatt Bloc Layout
|
||||
|
||||
<p align="left">
|
||||
<a href="https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages/src/branch/master/packages/wyatt_analysis">
|
||||
<img src="https://img.shields.io/badge/Style-Wyatt%20Analysis-blue.svg?style=flat-square" alt="Style: Wyatt Analysis" />
|
||||
</a>
|
||||
<img src="https://img.shields.io/badge/SDK-Dart-blue?style=flat-square" alt="SDK: Dart" />
|
||||
<img src="https://img.shields.io/badge/Status-WIP-red?style=flat-square" alt="WIP" />
|
||||
<img src="https://img.shields.io/badge/SDK-Flutter-blue?style=flat-square" alt="SDK: Flutter" />
|
||||
</p>
|
||||
|
||||
Bloc Layout for Flutter.
|
||||
|
||||
|
||||
TODO: Put a short description of the package here that helps potential users
|
||||
know whether this package might be useful for them.
|
||||
|
||||
## Features
|
||||
|
||||
TODO: List what your package can do. Maybe include images, gifs, or videos.
|
||||
<!-- TODO -->
|
||||
|
||||
## Getting started
|
||||
|
||||
TODO: List prerequisites and provide or point to information on how to
|
||||
start using the package.
|
||||
<!-- TODO -->
|
||||
|
||||
## Usage
|
||||
|
||||
TODO: Include short and useful examples for package users. Add longer examples
|
||||
to `/example` folder.
|
||||
|
||||
```dart
|
||||
const like = 'sample';
|
||||
```
|
||||
|
||||
## Additional information
|
||||
|
||||
TODO: Tell users more about the package: where to find more information, how to
|
||||
contribute to the package, how to file issues, what response they can expect
|
||||
from the package authors, and more.
|
||||
<!-- TODO -->
|
||||
@@ -0,0 +1,19 @@
|
||||
# Copyright (C) 2022 WYATT GROUP
|
||||
# Please see the AUTHORS file for details.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
include: package:wyatt_analysis/analysis_options.flutter.experimental.yaml
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user