Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 |
@@ -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,32 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## 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
|
## 2022-12-04
|
||||||
|
|
||||||
### Changes
|
### 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 :
|
Before closing the issue, please check tests and update coverage. You might run :
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
melos run test
|
melos run test:all # this will run all tests in this project
|
||||||
melos run gen_coverage
|
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
|
#### 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.
|
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.
|
||||||
|
|||||||
@@ -21,8 +21,7 @@ scripts:
|
|||||||
|
|
||||||
analyze:
|
analyze:
|
||||||
run: |
|
run: |
|
||||||
melos exec -c 10 -- \
|
melos exec -c 1 -- flutter analyze --fatal-infos
|
||||||
flutter analyze --fatal-infos
|
|
||||||
description: Run `flutter analyze` for all packages.
|
description: Run `flutter analyze` for all packages.
|
||||||
|
|
||||||
format:
|
format:
|
||||||
@@ -38,18 +37,38 @@ scripts:
|
|||||||
description: Clean things very deeply with `git clean`.
|
description: Clean things very deeply with `git clean`.
|
||||||
|
|
||||||
test:selective_unit_test:
|
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.
|
description: Run Flutter tests for a specific package in this project.
|
||||||
select-package:
|
select-package:
|
||||||
flutter: true
|
dir-exists:
|
||||||
|
- test
|
||||||
|
ignore:
|
||||||
|
- '*example*'
|
||||||
|
|
||||||
test:
|
test:all:
|
||||||
run: melos run test:selective_unit_test --no-select
|
run: melos run test:selective_unit_test --no-select
|
||||||
description: Run all Flutter tests in this project.
|
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-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.
|
# Additional cleanup lifecycle script, executed when `melos clean` is run.
|
||||||
postclean: >
|
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
|
## 2.2.2
|
||||||
|
|
||||||
- **DOCS**: add publish_to self hosted pub server.
|
- **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).
|
**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`:
|
To use the lints, add a dependency in your `pubspec.yaml`:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
dev_dependencies:
|
|
||||||
wyatt_analysis:
|
wyatt_analysis:
|
||||||
git:
|
hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub/
|
||||||
url: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages
|
version: 2.3.0
|
||||||
ref: wyatt_analysis-v2.0.0
|
|
||||||
path: packages/wyatt_analysis
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Then, add an include in `analysis_options.yaml`:
|
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:
|
If you wish to restrict the lint version, specify a version of `analysis_options.yaml` instead:
|
||||||
|
|
||||||
```yaml
|
```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:
|
If you just want **Dart** version:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
include: package:wyatt_analysis/analysis_options.2.0.0.yaml
|
include: package:wyatt_analysis/analysis_options.2.3.0.yaml
|
||||||
```
|
```
|
||||||
|
|
||||||
## Suppressing Lints
|
## 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
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
# 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:
|
linter:
|
||||||
rules:
|
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
|
# Copyright (C) 2022 WYATT GROUP
|
||||||
# Please see the AUTHORS file for details.
|
# Please see the AUTHORS file for details.
|
||||||
#
|
#
|
||||||
@@ -14,4 +15,5 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
# 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
|
# Copyright (C) 2022 WYATT GROUP
|
||||||
# Please see the AUTHORS file for details.
|
# Please see the AUTHORS file for details.
|
||||||
#
|
#
|
||||||
@@ -14,4 +15,5 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
# 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/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
/// Wyatt analyzer settings and best practices
|
/// Wyatt analyzer settings and best practices
|
||||||
/// used internally at [Wyatt](https://wyattapp.io)
|
/// used internally at [Wyatt Studio](https://wyatt-studio.fr).
|
||||||
/// and [Wyatt Studio](https://wyatt-studio.fr).
|
|
||||||
library wyatt_analysis;
|
library wyatt_analysis;
|
||||||
|
|
||||||
const String wyattAnalysisVersion = '2.2.1';
|
const String wyattAnalysisVersion = '2.3.0';
|
||||||
|
|||||||
@@ -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
|
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
|
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
|
publish_to: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub
|
||||||
|
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ dev_dependencies:
|
|||||||
wyatt_analysis:
|
wyatt_analysis:
|
||||||
git:
|
git:
|
||||||
url: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages
|
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
|
path: packages/wyatt_analysis
|
||||||
|
|
||||||
# For information on the generic Dart part of this file, see the
|
# For information on the generic Dart part of this file, see the
|
||||||
|
|||||||
@@ -24,4 +24,4 @@ dev_dependencies:
|
|||||||
|
|
||||||
wyatt_analysis:
|
wyatt_analysis:
|
||||||
hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub
|
hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub
|
||||||
version: ^2.2.2
|
version: ^2.3.0
|
||||||
@@ -1,11 +1,18 @@
|
|||||||
// Author: Hugo Pointcheval
|
// Copyright (C) 2022 WYATT GROUP
|
||||||
// Email: git@pcl.ovh
|
// Please see the AUTHORS file for details.
|
||||||
// -----
|
//
|
||||||
// File: bootstrap.dart
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// Created Date: 19/08/2022 15:05:17
|
// it under the terms of the GNU General Public License as published by
|
||||||
// Last Modified: Fri Nov 11 2022
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
// -----
|
// any later version.
|
||||||
// Copyright (c) 2022
|
//
|
||||||
|
// 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:async';
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,20 @@
|
|||||||
// Author: Hugo Pointcheval
|
// Copyright (C) 2022 WYATT GROUP
|
||||||
// Email: git@pcl.ovh
|
// Please see the AUTHORS file for details.
|
||||||
// -----
|
//
|
||||||
// File: form_field.dart
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// Created Date: 19/08/2022 11:52:33
|
// it under the terms of the GNU General Public License as published by
|
||||||
// Last Modified: 19/08/2022 16:35:39
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
// -----
|
// any later version.
|
||||||
// Copyright (c) 2022
|
//
|
||||||
|
// 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 {
|
abstract class AppFormField {
|
||||||
|
static const oldPassword = 'oldPassword';
|
||||||
static const confirmedPassword = 'confirmedPassword';
|
static const confirmedPassword = 'confirmedPassword';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,6 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import 'dart:io';
|
abstract class AppFormName {
|
||||||
|
static const editProfile = 'editProfile';
|
||||||
bool get supportsAnsiColor => stdout.supportsAnsiEscapes;
|
}
|
||||||
@@ -1,12 +1,20 @@
|
|||||||
// Author: Hugo Pointcheval
|
// Copyright (C) 2022 WYATT GROUP
|
||||||
// Email: git@pcl.ovh
|
// Please see the AUTHORS file for details.
|
||||||
// -----
|
//
|
||||||
// File: router.dart
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// Created Date: 19/08/2022 11:52:22
|
// it under the terms of the GNU General Public License as published by
|
||||||
// Last Modified: 19/08/2022 16:39:07
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
// -----
|
// any later version.
|
||||||
// Copyright (c) 2022
|
//
|
||||||
|
// 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/home/home_page.dart';
|
||||||
import 'package:example_router/presentation/features/sign_in/sign_in_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';
|
import 'package:example_router/presentation/features/sign_up/sign_up_page.dart';
|
||||||
@@ -75,5 +83,14 @@ class AppRouter {
|
|||||||
const SubPage(),
|
const SubPage(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
GoRoute(
|
||||||
|
path: '/home/edit',
|
||||||
|
name: EditProfilePage.pageName,
|
||||||
|
pageBuilder: (context, state) => defaultTransition(
|
||||||
|
context,
|
||||||
|
state,
|
||||||
|
const EditProfilePage(),
|
||||||
|
),
|
||||||
|
),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,18 @@
|
|||||||
// Author: Hugo Pointcheval
|
// Copyright (C) 2022 WYATT GROUP
|
||||||
// Email: git@pcl.ovh
|
// Please see the AUTHORS file for details.
|
||||||
// -----
|
//
|
||||||
// File: app_bloc_observer.dart
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// Created Date: 19/08/2022 12:02:23
|
// it under the terms of the GNU General Public License as published by
|
||||||
// Last Modified: 19/08/2022 12:02:45
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
// -----
|
// any later version.
|
||||||
// Copyright (c) 2022
|
//
|
||||||
|
// 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/foundation.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|||||||
@@ -14,37 +14,19 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// 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 State<W extends Widget<dynamic>> {
|
abstract class AppForms {
|
||||||
W? _widget;
|
static WyattForm getEditProfileForm() => WyattFormImpl(
|
||||||
W get widget => _widget!;
|
[
|
||||||
|
FormInput(AuthFormField.email, const Email.pure()),
|
||||||
BuildContext? _context;
|
FormInput(AuthFormField.password, const CustomPassword.pure()),
|
||||||
BuildContext get context => _context!;
|
FormInput(AppFormField.oldPassword, const CustomPassword.pure()),
|
||||||
|
],
|
||||||
void build();
|
name: AppFormName.editProfile,
|
||||||
|
);
|
||||||
dynamic prompt();
|
|
||||||
|
|
||||||
@protected
|
|
||||||
@mustCallSuper
|
|
||||||
void dispose() {
|
|
||||||
_context = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@protected
|
|
||||||
@mustCallSuper
|
|
||||||
void initState() {
|
|
||||||
_context ??= BuildContext();
|
|
||||||
}
|
|
||||||
|
|
||||||
@protected
|
|
||||||
@mustCallSuper
|
|
||||||
void setState(void Function() fn) {
|
|
||||||
fn();
|
|
||||||
context.wipe();
|
|
||||||
build();
|
|
||||||
context.incrementBuildCount();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,3 +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/>.
|
||||||
|
|
||||||
import 'package:example_router/bootstrap.dart';
|
import 'package:example_router/bootstrap.dart';
|
||||||
import 'package:example_router/presentation/features/app/app.dart';
|
import 'package:example_router/presentation/features/app/app.dart';
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,18 @@
|
|||||||
// Author: Hugo Pointcheval
|
// Copyright (C) 2022 WYATT GROUP
|
||||||
// Email: git@pcl.ovh
|
// Please see the AUTHORS file for details.
|
||||||
// -----
|
//
|
||||||
// File: app.dart
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// Created Date: 19/08/2022 12:05:38
|
// it under the terms of the GNU General Public License as published by
|
||||||
// Last Modified: Sat Dec 03 2022
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
// -----
|
// any later version.
|
||||||
// Copyright (c) 2022
|
//
|
||||||
|
// 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:async';
|
||||||
import 'dart:math';
|
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/dependency_injection/get_it.dart';
|
||||||
import 'package:example_router/core/routes/router.dart';
|
import 'package:example_router/core/routes/router.dart';
|
||||||
import 'package:example_router/core/utils/custom_password.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/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
@@ -69,7 +77,7 @@ class App extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
AuthenticationState? previous;
|
AuthenticationState<int>? previous;
|
||||||
|
|
||||||
final AuthenticationCubit<int> authenticationCubit =
|
final AuthenticationCubit<int> authenticationCubit =
|
||||||
AuthenticationCubit(authenticationRepository: authenticationRepository);
|
AuthenticationCubit(authenticationRepository: authenticationRepository);
|
||||||
@@ -85,29 +93,18 @@ class App extends StatelessWidget {
|
|||||||
redirect: (context, state) {
|
redirect: (context, state) {
|
||||||
final authState = authenticationCubit.state;
|
final authState = authenticationCubit.state;
|
||||||
|
|
||||||
if (authState != previous) {
|
if (authState.status != previous?.status) {
|
||||||
previous = authState;
|
previous = authState;
|
||||||
// Check if current user is logged in
|
|
||||||
final loggedIn =
|
|
||||||
authState.status == AuthenticationStatus.authenticated;
|
|
||||||
|
|
||||||
// Checking if current path is onboarding or not
|
// Checking if current path is onboarding or not
|
||||||
final isOnboarding = AppRouter.publicRoutes.contains(state.subloc);
|
final isOnboarding = AppRouter.publicRoutes.contains(state.subloc);
|
||||||
|
if (authState.status == AuthenticationStatus.unauthenticated) {
|
||||||
if (!loggedIn) {
|
|
||||||
debugPrint('Not logged');
|
debugPrint('Not logged');
|
||||||
if (isOnboarding) {
|
if (!isOnboarding) {
|
||||||
return null;
|
|
||||||
} else {
|
|
||||||
return '/';
|
return '/';
|
||||||
}
|
}
|
||||||
} else {
|
} else if (authState.status == AuthenticationStatus.authenticated) {
|
||||||
debugPrint('Logged');
|
debugPrint('Logged');
|
||||||
if (isOnboarding) {
|
|
||||||
return '/home';
|
return '/home';
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@@ -116,9 +113,13 @@ class App extends StatelessWidget {
|
|||||||
|
|
||||||
return MultiRepositoryProvider(
|
return MultiRepositoryProvider(
|
||||||
providers: [
|
providers: [
|
||||||
RepositoryProvider<AuthenticationRepository>.value(
|
RepositoryProvider<AuthenticationRepository<int>>.value(
|
||||||
value: authenticationRepository,
|
value: authenticationRepository,
|
||||||
),
|
),
|
||||||
|
RepositoryProvider<FormRepository>(
|
||||||
|
create: (context) =>
|
||||||
|
FormRepositoryImpl()..registerForm(AppForms.getEditProfileForm()),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
child: MultiBlocProvider(
|
child: MultiBlocProvider(
|
||||||
providers: [
|
providers: [
|
||||||
|
|||||||
@@ -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));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,12 +1,20 @@
|
|||||||
// Author: Hugo Pointcheval
|
// Copyright (C) 2022 WYATT GROUP
|
||||||
// Email: git@pcl.ovh
|
// Please see the AUTHORS file for details.
|
||||||
// -----
|
//
|
||||||
// File: home_page.dart
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// Created Date: 19/08/2022 14:38:24
|
// it under the terms of the GNU General Public License as published by
|
||||||
// Last Modified: Wed Nov 09 2022
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
// -----
|
// any later version.
|
||||||
// Copyright (c) 2022
|
//
|
||||||
|
// 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:example_router/presentation/features/sub/sub_page.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
@@ -25,7 +33,8 @@ class HomePage extends StatelessWidget {
|
|||||||
title: const Text('Home'),
|
title: const Text('Home'),
|
||||||
actions: [
|
actions: [
|
||||||
IconButton(
|
IconButton(
|
||||||
onPressed: () => context.read<AuthenticationCubit<int>>().signOut(),
|
onPressed: () =>
|
||||||
|
context.read<AuthenticationCubit<int>>().signOut(),
|
||||||
icon: const Icon(Icons.logout_rounded))
|
icon: const Icon(Icons.logout_rounded))
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -35,8 +44,8 @@ class HomePage extends StatelessWidget {
|
|||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
AuthenticationBuilder<int>(
|
AuthenticationBuilder<int>(
|
||||||
authenticated: (context, accountWrapper) =>
|
authenticated: (context, accountWrapper) => Text(
|
||||||
Text('Logged as ${accountWrapper.account?.email} | GeneratedId is ${accountWrapper.data}'),
|
'Logged as ${accountWrapper.account?.email} | GeneratedId is ${accountWrapper.data}'),
|
||||||
unauthenticated: (context) =>
|
unauthenticated: (context) =>
|
||||||
const Text('Not logged (unauthenticated)'),
|
const Text('Not logged (unauthenticated)'),
|
||||||
unknown: (context) => const Text('Not logged (unknown)'),
|
unknown: (context) => const Text('Not logged (unknown)'),
|
||||||
@@ -46,7 +55,12 @@ class HomePage extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
onPressed: () => context.pushNamed(SubPage.pageName),
|
onPressed: () => context.pushNamed(SubPage.pageName),
|
||||||
child: const Text('Go to sub page')),
|
child: const Text('Go to sub page'),
|
||||||
|
),
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () => context.pushNamed(EditProfilePage.pageName),
|
||||||
|
child: const Text('Go to edit profile page'),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -1,11 +1,18 @@
|
|||||||
// Author: Hugo Pointcheval
|
// Copyright (C) 2022 WYATT GROUP
|
||||||
// Email: git@pcl.ovh
|
// Please see the AUTHORS file for details.
|
||||||
// -----
|
//
|
||||||
// File: sign_in_page.dart
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// Created Date: 19/08/2022 12:41:42
|
// it under the terms of the GNU General Public License as published by
|
||||||
// Last Modified: 19/08/2022 15:26:36
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
// -----
|
// any later version.
|
||||||
// Copyright (c) 2022
|
//
|
||||||
|
// 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:example_router/presentation/features/sign_in/widgets/sign_in_form.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|||||||
@@ -1,11 +1,18 @@
|
|||||||
// Author: Hugo Pointcheval
|
// Copyright (C) 2022 WYATT GROUP
|
||||||
// Email: git@pcl.ovh
|
// Please see the AUTHORS file for details.
|
||||||
// -----
|
//
|
||||||
// File: sign_in_form.dart
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// Created Date: 19/08/2022 15:24:37
|
// it under the terms of the GNU General Public License as published by
|
||||||
// Last Modified: Sat Dec 03 2022
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
// -----
|
// any later version.
|
||||||
// Copyright (c) 2022
|
//
|
||||||
|
// 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:example_router/core/utils/custom_password.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|||||||
@@ -1,11 +1,18 @@
|
|||||||
// Author: Hugo Pointcheval
|
// Copyright (C) 2022 WYATT GROUP
|
||||||
// Email: git@pcl.ovh
|
// Please see the AUTHORS file for details.
|
||||||
// -----
|
//
|
||||||
// File: sign_up_page.dart
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// Created Date: 19/08/2022 12:41:27
|
// it under the terms of the GNU General Public License as published by
|
||||||
// Last Modified: 19/08/2022 14:58:51
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
// -----
|
// any later version.
|
||||||
// Copyright (c) 2022
|
//
|
||||||
|
// 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:example_router/presentation/features/sign_up/widgets/sign_up_form.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|||||||
@@ -1,11 +1,18 @@
|
|||||||
// Author: Hugo Pointcheval
|
// Copyright (C) 2022 WYATT GROUP
|
||||||
// Email: git@pcl.ovh
|
// Please see the AUTHORS file for details.
|
||||||
// -----
|
//
|
||||||
// File: sign_up_form.dart
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// Created Date: 19/08/2022 14:41:08
|
// it under the terms of the GNU General Public License as published by
|
||||||
// Last Modified: Sat Dec 03 2022
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
// -----
|
// any later version.
|
||||||
// Copyright (c) 2022
|
//
|
||||||
|
// 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/constants/form_field.dart';
|
||||||
import 'package:example_router/core/utils/custom_password.dart';
|
import 'package:example_router/core/utils/custom_password.dart';
|
||||||
|
|||||||
@@ -1,11 +1,18 @@
|
|||||||
// Author: Hugo Pointcheval
|
// Copyright (C) 2022 WYATT GROUP
|
||||||
// Email: git@pcl.ovh
|
// Please see the AUTHORS file for details.
|
||||||
// -----
|
//
|
||||||
// File: sub_page.dart
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// Created Date: 19/08/2022 16:10:05
|
// it under the terms of the GNU General Public License as published by
|
||||||
// Last Modified: Wed Nov 09 2022
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
// -----
|
// any later version.
|
||||||
// Copyright (c) 2022
|
//
|
||||||
|
// 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/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
@@ -24,7 +31,10 @@ class SubPage extends StatelessWidget {
|
|||||||
actions: [
|
actions: [
|
||||||
IconButton(
|
IconButton(
|
||||||
onPressed: () => context.read<AuthenticationCubit<int>>().signOut(),
|
onPressed: () => context.read<AuthenticationCubit<int>>().signOut(),
|
||||||
icon: const Icon(Icons.logout_rounded))
|
icon: const Icon(Icons.logout_rounded)),
|
||||||
|
IconButton(
|
||||||
|
onPressed: () => context.read<AuthenticationRepository<int>>().refresh(),
|
||||||
|
icon: const Icon(Icons.refresh))
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
body: const Padding(
|
body: const Padding(
|
||||||
|
|||||||
@@ -1,11 +1,18 @@
|
|||||||
// Author: Hugo Pointcheval
|
// Copyright (C) 2022 WYATT GROUP
|
||||||
// Email: git@pcl.ovh
|
// Please see the AUTHORS file for details.
|
||||||
// -----
|
//
|
||||||
// File: welcome_page.dart
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// Created Date: 19/08/2022 12:33:21
|
// it under the terms of the GNU General Public License as published by
|
||||||
// Last Modified: Wed Nov 09 2022
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
// -----
|
// any later version.
|
||||||
// Copyright (c) 2022
|
//
|
||||||
|
// 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_in/sign_in_page.dart';
|
||||||
import 'package:example_router/presentation/features/sign_up/sign_up_page.dart';
|
import 'package:example_router/presentation/features/sign_up/sign_up_page.dart';
|
||||||
|
|||||||
@@ -256,3 +256,24 @@ abstract class GetIdTokenFailureInterface
|
|||||||
|
|
||||||
GetIdTokenFailureInterface.fromCode(super.code) : super.fromCode();
|
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();
|
||||||
|
}
|
||||||
|
|||||||
@@ -277,3 +277,75 @@ class GetIdTokenFailureFirebase extends GetIdTokenFailureInterface {
|
|||||||
|
|
||||||
GetIdTokenFailureFirebase.fromCode(super.code) : super.fromCode();
|
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.';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import 'package:wyatt_type_utils/wyatt_type_utils.dart';
|
|||||||
class AuthenticationFirebaseDataSourceImpl
|
class AuthenticationFirebaseDataSourceImpl
|
||||||
extends AuthenticationRemoteDataSource {
|
extends AuthenticationRemoteDataSource {
|
||||||
final FirebaseAuth _firebaseAuth;
|
final FirebaseAuth _firebaseAuth;
|
||||||
|
UserCredential? _latestCreds;
|
||||||
|
|
||||||
AuthenticationFirebaseDataSourceImpl({FirebaseAuth? firebaseAuth})
|
AuthenticationFirebaseDataSourceImpl({FirebaseAuth? firebaseAuth})
|
||||||
: _firebaseAuth = firebaseAuth ?? FirebaseAuth.instance;
|
: _firebaseAuth = firebaseAuth ?? FirebaseAuth.instance;
|
||||||
@@ -51,6 +52,7 @@ class AuthenticationFirebaseDataSourceImpl
|
|||||||
email: email,
|
email: email,
|
||||||
password: password,
|
password: password,
|
||||||
);
|
);
|
||||||
|
_latestCreds = userCredential;
|
||||||
final user = userCredential.user;
|
final user = userCredential.user;
|
||||||
if (user.isNotNull) {
|
if (user.isNotNull) {
|
||||||
return _mapper(user!);
|
return _mapper(user!);
|
||||||
@@ -76,6 +78,7 @@ class AuthenticationFirebaseDataSourceImpl
|
|||||||
email: email,
|
email: email,
|
||||||
password: password,
|
password: password,
|
||||||
);
|
);
|
||||||
|
_latestCreds = userCredential;
|
||||||
final user = userCredential.user;
|
final user = userCredential.user;
|
||||||
if (user.isNotNull) {
|
if (user.isNotNull) {
|
||||||
return _mapper(user!);
|
return _mapper(user!);
|
||||||
@@ -92,6 +95,7 @@ class AuthenticationFirebaseDataSourceImpl
|
|||||||
@override
|
@override
|
||||||
Future<void> signOut() async {
|
Future<void> signOut() async {
|
||||||
try {
|
try {
|
||||||
|
_latestCreds = null;
|
||||||
await _firebaseAuth.signOut();
|
await _firebaseAuth.signOut();
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
throw SignOutFailureFirebase();
|
throw SignOutFailureFirebase();
|
||||||
@@ -164,6 +168,7 @@ class AuthenticationFirebaseDataSourceImpl
|
|||||||
Future<Account> signInAnonymously() async {
|
Future<Account> signInAnonymously() async {
|
||||||
try {
|
try {
|
||||||
final userCredential = await _firebaseAuth.signInAnonymously();
|
final userCredential = await _firebaseAuth.signInAnonymously();
|
||||||
|
_latestCreds = userCredential;
|
||||||
final user = userCredential.user;
|
final user = userCredential.user;
|
||||||
if (user.isNotNull) {
|
if (user.isNotNull) {
|
||||||
return _mapper(user!);
|
return _mapper(user!);
|
||||||
@@ -199,4 +204,60 @@ class AuthenticationFirebaseDataSourceImpl
|
|||||||
throw RefreshFailureFirebase();
|
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;
|
||||||
|
if (user.isNotNull) {
|
||||||
|
return _mapper(user!);
|
||||||
|
} else {
|
||||||
|
throw Exception(); // Get caught just after.
|
||||||
|
}
|
||||||
|
} 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;
|
||||||
|
if (user.isNotNull) {
|
||||||
|
return _mapper(user!);
|
||||||
|
} else {
|
||||||
|
throw Exception(); // Get caught just after.
|
||||||
|
}
|
||||||
|
} 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;
|
||||||
|
if (user.isNotNull) {
|
||||||
|
return _mapper(user!);
|
||||||
|
} else {
|
||||||
|
throw Exception(); // Get caught just after.
|
||||||
|
}
|
||||||
|
} on FirebaseAuthException catch (e) {
|
||||||
|
throw UpdatePasswordFailureFirebase.fromCode(e.code);
|
||||||
|
} catch (_) {
|
||||||
|
throw UpdatePasswordFailureFirebase();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import 'package:wyatt_type_utils/wyatt_type_utils.dart';
|
|||||||
class AuthenticationMockDataSourceImpl extends AuthenticationRemoteDataSource {
|
class AuthenticationMockDataSourceImpl extends AuthenticationRemoteDataSource {
|
||||||
Pair<Account, String>? _connectedMock;
|
Pair<Account, String>? _connectedMock;
|
||||||
Pair<Account, String>? _registeredMock;
|
Pair<Account, String>? _registeredMock;
|
||||||
|
DateTime _lastSignInTime = DateTime.now();
|
||||||
final StreamController<Account?> _streamAccount = StreamController()
|
final StreamController<Account?> _streamAccount = StreamController()
|
||||||
..add(null);
|
..add(null);
|
||||||
|
|
||||||
@@ -118,6 +119,7 @@ class AuthenticationMockDataSourceImpl extends AuthenticationRemoteDataSource {
|
|||||||
);
|
);
|
||||||
_streamAccount.add(mock);
|
_streamAccount.add(mock);
|
||||||
_connectedMock = _connectedMock?.copyWith(left: mock);
|
_connectedMock = _connectedMock?.copyWith(left: mock);
|
||||||
|
_lastSignInTime = DateTime.now();
|
||||||
return Future.value(mock);
|
return Future.value(mock);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,6 +151,7 @@ class AuthenticationMockDataSourceImpl extends AuthenticationRemoteDataSource {
|
|||||||
}
|
}
|
||||||
_streamAccount.add(_registeredMock!.left);
|
_streamAccount.add(_registeredMock!.left);
|
||||||
_connectedMock = _registeredMock!.copyWith();
|
_connectedMock = _registeredMock!.copyWith();
|
||||||
|
_lastSignInTime = DateTime.now();
|
||||||
return _registeredMock!.left!;
|
return _registeredMock!.left!;
|
||||||
}
|
}
|
||||||
throw SignInWithCredentialFailureFirebase();
|
throw SignInWithCredentialFailureFirebase();
|
||||||
@@ -193,6 +196,8 @@ class AuthenticationMockDataSourceImpl extends AuthenticationRemoteDataSource {
|
|||||||
);
|
);
|
||||||
_streamAccount.add(mock);
|
_streamAccount.add(mock);
|
||||||
_registeredMock = Pair(mock, password);
|
_registeredMock = Pair(mock, password);
|
||||||
|
_connectedMock = _registeredMock!.copyWith();
|
||||||
|
_lastSignInTime = DateTime.now();
|
||||||
return Future.value(mock);
|
return Future.value(mock);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -204,4 +209,45 @@ class AuthenticationMockDataSourceImpl extends AuthenticationRemoteDataSource {
|
|||||||
await _randomDelay();
|
await _randomDelay();
|
||||||
return true;
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -314,4 +314,38 @@ class AuthenticationRepositoryImpl<T extends Object>
|
|||||||
},
|
},
|
||||||
(error) => error,
|
(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,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,4 +48,10 @@ abstract class AuthenticationRemoteDataSource extends BaseRemoteDataSource {
|
|||||||
Future<bool> verifyPasswordResetCode({required String code});
|
Future<bool> verifyPasswordResetCode({required String code});
|
||||||
|
|
||||||
Future<Account> signInAnonymously();
|
Future<Account> signInAnonymously();
|
||||||
|
|
||||||
|
Future<Account> updateEmail({required String email});
|
||||||
|
|
||||||
|
Future<Account> updatePassword({required String password});
|
||||||
|
|
||||||
|
Future<Account> reauthenticateWithCredential();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -84,12 +84,45 @@ abstract class AuthenticationRepository<T> extends BaseRepository {
|
|||||||
required String password,
|
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}
|
/// {@template signout}
|
||||||
/// Signs out the current user.
|
/// Signs out the current user.
|
||||||
/// It also clears the cache and the associated data.
|
/// It also clears the cache and the associated data.
|
||||||
/// {@endtemplate}
|
/// {@endtemplate}
|
||||||
FutureOrResult<void> signOut();
|
FutureOrResult<void> signOut();
|
||||||
|
|
||||||
|
/// {@template refresh}
|
||||||
|
/// Refreshes the current user, if signed in.
|
||||||
|
/// {@endtemplate}
|
||||||
FutureOrResult<void> refresh();
|
FutureOrResult<void> refresh();
|
||||||
|
|
||||||
/// {@template stream_account}
|
/// {@template stream_account}
|
||||||
|
|||||||
@@ -43,4 +43,4 @@ dev_dependencies:
|
|||||||
|
|
||||||
wyatt_analysis:
|
wyatt_analysis:
|
||||||
hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub/
|
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:
|
wyatt_analysis:
|
||||||
hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub
|
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
|
||||||
@@ -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"
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -4,4 +4,5 @@
|
|||||||
# Name/Organization <email address>
|
# Name/Organization <email address>
|
||||||
|
|
||||||
Wyatt Group S.A.S
|
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
|
* Copyright (C) 2022 WYATT GROUP
|
||||||
* Please see the AUTHORS file for details.
|
* Please see the AUTHORS file for details.
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* any later version.
|
* any later version.
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
# Dart - CLI Toolbox
|
|
||||||
|
# Flutter - Wyatt Bloc Layout
|
||||||
|
|
||||||
<p align="left">
|
<p align="left">
|
||||||
<a href="https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages/src/branch/master/packages/wyatt_analysis">
|
<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" />
|
<img src="https://img.shields.io/badge/Style-Wyatt%20Analysis-blue.svg?style=flat-square" alt="Style: Wyatt Analysis" />
|
||||||
</a>
|
</a>
|
||||||
<img src="https://img.shields.io/badge/SDK-Dart-blue?style=flat-square" alt="SDK: Dart" />
|
<img src="https://img.shields.io/badge/SDK-Flutter-blue?style=flat-square" alt="SDK: Flutter" />
|
||||||
<img src="https://img.shields.io/badge/Status-WIP-red?style=flat-square" alt="WIP" />
|
|
||||||
</p>
|
</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
|
## Features
|
||||||
|
|
||||||
TODO: List what your package can do. Maybe include images, gifs, or videos.
|
<!-- TODO -->
|
||||||
|
|
||||||
## Getting started
|
## Getting started
|
||||||
|
|
||||||
TODO: List prerequisites and provide or point to information on how to
|
<!-- TODO -->
|
||||||
start using the package.
|
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
TODO: Include short and useful examples for package users. Add longer examples
|
<!-- TODO -->
|
||||||
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.
|
|
||||||
@@ -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
|
||||||
|
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:wyatt_bloc_layout/wyatt_bloc_layout.dart';
|
||||||
|
|
||||||
|
class ExampleCubit extends Cubit<CrudState> {
|
||||||
|
ExampleCubit() : super(CrudInitial());
|
||||||
|
|
||||||
|
FutureOr<void> run() async {
|
||||||
|
while (true) {
|
||||||
|
await Future.delayed(const Duration(seconds: 1));
|
||||||
|
emit(CrudLoading());
|
||||||
|
await Future.delayed(const Duration(seconds: 1));
|
||||||
|
emit(CrudError('Cubit Error'));
|
||||||
|
await Future.delayed(const Duration(seconds: 1));
|
||||||
|
emit(CrudLoaded<String>('DATA LOADED'));
|
||||||
|
await Future.delayed(const Duration(seconds: 1));
|
||||||
|
emit(CrudInitial());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FutureOr<void> runList() async {
|
||||||
|
while (true) {
|
||||||
|
await Future.delayed(const Duration(seconds: 1));
|
||||||
|
emit(CrudLoading());
|
||||||
|
await Future.delayed(const Duration(seconds: 1));
|
||||||
|
emit(CrudError('Cubit Error'));
|
||||||
|
await Future.delayed(const Duration(seconds: 1));
|
||||||
|
emit(CrudListLoaded<String>([
|
||||||
|
'DATA LOADED 1',
|
||||||
|
'DATA LOADED 2',
|
||||||
|
'DATA LOADED 3',
|
||||||
|
'DATA LOADED 4'
|
||||||
|
]));
|
||||||
|
await Future.delayed(const Duration(seconds: 1));
|
||||||
|
emit(CrudInitial());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:wyatt_bloc_layout/wyatt_bloc_layout.dart';
|
||||||
|
|
||||||
|
class AppThemeComponent {
|
||||||
|
static ComponentThemeData get components => ComponentThemeData.raw(
|
||||||
|
appBar: CustomAppBar(),
|
||||||
|
bottomNavigationBar: CustomBottomBar(),
|
||||||
|
loadingWidget: CustomLoadingWidget(),
|
||||||
|
errorWidget: CustomErrorWidget(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
class CustomAppBar extends AppBarComponent {
|
||||||
|
const CustomAppBar({super.title});
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) => AppBar(
|
||||||
|
title: Text(title ?? 'Title'),
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
AppBarComponent? configure(
|
||||||
|
{String? title, Widget? leading, List<Widget>? actions}) =>
|
||||||
|
CustomAppBar(
|
||||||
|
title: title ?? this.title,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
class CustomBottomBar extends BottomNavigationBarComponent {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) => BottomNavigationBar(
|
||||||
|
items: [
|
||||||
|
BottomNavigationBarItem(
|
||||||
|
icon: Icon(
|
||||||
|
Icons.e_mobiledata,
|
||||||
|
),
|
||||||
|
label: 'Icon 1'),
|
||||||
|
BottomNavigationBarItem(
|
||||||
|
icon: Icon(
|
||||||
|
Icons.do_not_disturb_off,
|
||||||
|
),
|
||||||
|
label: 'Icon 2'),
|
||||||
|
],
|
||||||
|
backgroundColor: Colors.blue,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
BottomNavigationBarComponent? configure(
|
||||||
|
{void Function(BuildContext p1, int p2)? onTap,
|
||||||
|
int currentIndex = 0}) =>
|
||||||
|
this;
|
||||||
|
}
|
||||||
|
|
||||||
|
class CustomLoadingWidget extends LoadingWidgetComponent {
|
||||||
|
CustomLoadingWidget({super.color});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) =>
|
||||||
|
Center(child: CircularProgressIndicator(color: color));
|
||||||
|
|
||||||
|
@override
|
||||||
|
LoadingWidgetComponent? configure({Color? color}) => CustomLoadingWidget(
|
||||||
|
color: color ?? this.color,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
class CustomErrorWidget extends ErrorWidgetComponent {
|
||||||
|
CustomErrorWidget({super.error});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) => ColoredBox(
|
||||||
|
color: Colors.red,
|
||||||
|
child: Center(child: Text(error ?? 'Error')),
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
ErrorWidgetComponent? configure({String? error}) => CustomErrorWidget(
|
||||||
|
error: error ?? this.error,
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,134 @@
|
|||||||
|
// 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:bloc_layout_example/bloc/example_cubit.dart';
|
||||||
|
import 'package:bloc_layout_example/components/theme_components.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:wyatt_bloc_layout/wyatt_bloc_layout.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
runApp(const MyApp());
|
||||||
|
}
|
||||||
|
|
||||||
|
class MyApp extends StatelessWidget {
|
||||||
|
const MyApp({super.key});
|
||||||
|
|
||||||
|
// This widget is the root of your application.
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return ComponentTheme(
|
||||||
|
componentThemeWidget: AppThemeComponent.components,
|
||||||
|
child: MaterialApp(
|
||||||
|
title: 'Bloc Layout Example',
|
||||||
|
theme: ThemeData(
|
||||||
|
primarySwatch: Colors.blue,
|
||||||
|
),
|
||||||
|
home: Scaffold(
|
||||||
|
body: Column(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: BlocProvider(
|
||||||
|
create: (_) => ExampleCubit()..run(),
|
||||||
|
child: ExampleCrudStateManagement(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: BlocProvider(
|
||||||
|
create: (_) => ExampleCubit()..runList(),
|
||||||
|
child: ExampleListCrudStateManagement(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: BlocProvider(
|
||||||
|
create: (_) => ExampleCubit()..run(),
|
||||||
|
child: ExampleFrameLayoutCrudConsumer()),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: BlocProvider(
|
||||||
|
create: (_) => ExampleCubit()..runList(),
|
||||||
|
child: ExampleFrameLayoutCrudListConsumer()),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ExampleCrudStateManagement
|
||||||
|
extends CrudCubitConsumerScreen<ExampleCubit, String> {
|
||||||
|
@override
|
||||||
|
Widget initialBuilder(BuildContext context, CrudInitial state) =>
|
||||||
|
Container(color: Colors.yellow);
|
||||||
|
@override
|
||||||
|
Widget successBuilder(BuildContext context, CrudLoaded<String> state) =>
|
||||||
|
Center(child: Text(state.data ?? 'errors'));
|
||||||
|
}
|
||||||
|
|
||||||
|
class ExampleListCrudStateManagement
|
||||||
|
extends CrudListCubitConsumerScreen<ExampleCubit, String> {
|
||||||
|
@override
|
||||||
|
Widget initialBuilder(BuildContext context, CrudInitial state) =>
|
||||||
|
Container(color: Colors.green);
|
||||||
|
@override
|
||||||
|
Widget successBuilder(BuildContext context, CrudListLoaded<String> state) =>
|
||||||
|
Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: state.data.map((e) => Text(e ?? 'error')).toList(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
class ExampleFrameLayoutCrudConsumer
|
||||||
|
extends FrameLayoutCrudConsumerScreen<ExampleCubit, String> {
|
||||||
|
const ExampleFrameLayoutCrudConsumer()
|
||||||
|
: super(
|
||||||
|
title: 'Example Title',
|
||||||
|
currentIndex: 0,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget successBuilder(BuildContext context, CrudLoaded<String> state) =>
|
||||||
|
Center(child: Text(state.data ?? 'errors'));
|
||||||
|
}
|
||||||
|
|
||||||
|
class ExampleFrameLayoutCrudListConsumer
|
||||||
|
extends FrameLayoutCrudListConsumerScreen<ExampleCubit, String> {
|
||||||
|
const ExampleFrameLayoutCrudListConsumer()
|
||||||
|
: super(
|
||||||
|
title: 'Example Title',
|
||||||
|
currentIndex: 0,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget successBuilder(BuildContext context, CrudListLoaded<String> state) =>
|
||||||
|
Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: state.data.map((e) => Text(e ?? 'error')).toList(),
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
name: medium_feeds_example
|
name: bloc_layout_example
|
||||||
description: A new Flutter project.
|
description: A new Flutter project.
|
||||||
|
|
||||||
# The following line prevents the package from being accidentally published to
|
# The following line prevents the package from being accidentally published to
|
||||||
@@ -18,7 +18,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
|||||||
version: 1.0.0+1
|
version: 1.0.0+1
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=2.16.2 <3.0.0"
|
sdk: ">=2.17.0 <3.0.0"
|
||||||
|
|
||||||
# Dependencies specify other packages that your package needs in order to work.
|
# Dependencies specify other packages that your package needs in order to work.
|
||||||
# To automatically upgrade your package dependencies to the latest versions
|
# To automatically upgrade your package dependencies to the latest versions
|
||||||
@@ -27,32 +27,30 @@ environment:
|
|||||||
# the latest version available on pub.dev. To see which dependencies have newer
|
# the latest version available on pub.dev. To see which dependencies have newer
|
||||||
# versions available, run `flutter pub outdated`.
|
# versions available, run `flutter pub outdated`.
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|
||||||
flutter:
|
flutter:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
|
|
||||||
|
|
||||||
wyatt_medium_feeds:
|
wyatt_bloc_layout:
|
||||||
path: ../
|
path: "../"
|
||||||
|
|
||||||
|
|
||||||
# The following adds the Cupertino Icons font to your application.
|
|
||||||
# Use with the CupertinoIcons class for iOS style icons.
|
|
||||||
cupertino_icons: ^1.0.2
|
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
|
|
||||||
flutter_test:
|
flutter_test:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
|
|
||||||
# The "flutter_lints" package below contains a set of recommended lints to
|
|
||||||
# encourage good coding practices. The lint set provided by the package is
|
wyatt_analysis:
|
||||||
# activated in the `analysis_options.yaml` file located at the root of your
|
git:
|
||||||
# package. See that file for information about deactivating specific lint
|
url: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages
|
||||||
# rules and activating additional ones.
|
ref: wyatt_analysis-v2.3.0
|
||||||
flutter_lints: ^2.0.0
|
path: packages/wyatt_analysis
|
||||||
|
|
||||||
# For information on the generic Dart part of this file, see the
|
# For information on the generic Dart part of this file, see the
|
||||||
# following page: https://dart.dev/tools/pub/pubspec
|
# following page: https://dart.dev/tools/pub/pubspec
|
||||||
|
|
||||||
|
|
||||||
# The following section is specific to Flutter.
|
# The following section is specific to Flutter.
|
||||||
flutter:
|
flutter:
|
||||||
|
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
// 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/>.
|
||||||
|
Before Width: | Height: | Size: 917 B After Width: | Height: | Size: 917 B |
|
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 5.2 KiB |
|
Before Width: | Height: | Size: 8.1 KiB After Width: | Height: | Size: 8.1 KiB |
|
Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 5.5 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
@@ -0,0 +1,58 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<!--
|
||||||
|
If you are serving your web app in a path other than the root, change the
|
||||||
|
href value below to reflect the base path you are serving from.
|
||||||
|
|
||||||
|
The path provided below has to start and end with a slash "/" in order for
|
||||||
|
it to work correctly.
|
||||||
|
|
||||||
|
For more details:
|
||||||
|
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base
|
||||||
|
|
||||||
|
This is a placeholder for base href that will be replaced by the value of
|
||||||
|
the `--base-href` argument provided to `flutter build`.
|
||||||
|
-->
|
||||||
|
<base href="$FLUTTER_BASE_HREF">
|
||||||
|
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta content="IE=Edge" http-equiv="X-UA-Compatible">
|
||||||
|
<meta name="description" content="A new Flutter project.">
|
||||||
|
|
||||||
|
<!-- iOS meta tags & icons -->
|
||||||
|
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||||
|
<meta name="apple-mobile-web-app-status-bar-style" content="black">
|
||||||
|
<meta name="apple-mobile-web-app-title" content="example">
|
||||||
|
<link rel="apple-touch-icon" href="icons/Icon-192.png">
|
||||||
|
|
||||||
|
<!-- Favicon -->
|
||||||
|
<link rel="icon" type="image/png" href="favicon.png"/>
|
||||||
|
|
||||||
|
<title>example</title>
|
||||||
|
<link rel="manifest" href="manifest.json">
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// The value below is injected by flutter build, do not touch.
|
||||||
|
var serviceWorkerVersion = null;
|
||||||
|
</script>
|
||||||
|
<!-- This script adds the flutter initialization JS code -->
|
||||||
|
<script src="flutter.js" defer></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<script>
|
||||||
|
window.addEventListener('load', function(ev) {
|
||||||
|
// Download main.dart.js
|
||||||
|
_flutter.loader.loadEntrypoint({
|
||||||
|
serviceWorker: {
|
||||||
|
serviceWorkerVersion: serviceWorkerVersion,
|
||||||
|
}
|
||||||
|
}).then(function(engineInitializer) {
|
||||||
|
return engineInitializer.initializeEngine();
|
||||||
|
}).then(function(appRunner) {
|
||||||
|
return appRunner.runApp();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "medium_feeds_example",
|
"name": "example",
|
||||||
"short_name": "medium_feeds_example",
|
"short_name": "example",
|
||||||
"start_url": ".",
|
"start_url": ".",
|
||||||
"display": "standalone",
|
"display": "standalone",
|
||||||
"background_color": "#0175C2",
|
"background_color": "#0175C2",
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
// 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' as bloc_base;
|
||||||
|
import 'package:wyatt_bloc_layout/wyatt_bloc_layout.dart';
|
||||||
|
|
||||||
|
abstract class AppBarLayoutCrudConsumerScreen<
|
||||||
|
Cubit extends bloc_base.Cubit<CrudState>,
|
||||||
|
T> extends CrudCubitConsumerScreen<Cubit, T> {
|
||||||
|
final String? title;
|
||||||
|
|
||||||
|
const AppBarLayoutCrudConsumerScreen({
|
||||||
|
this.title,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget parent(BuildContext context, Widget child) => AppBarLayout(
|
||||||
|
title: title ?? 'Title',
|
||||||
|
body: child,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class AppBarLayoutCrudListConsumerScreen<
|
||||||
|
Cubit extends bloc_base.Cubit<CrudState>,
|
||||||
|
T> extends CrudListCubitConsumerScreen<Cubit, T> {
|
||||||
|
final String? title;
|
||||||
|
final int? currentIndex;
|
||||||
|
|
||||||
|
const AppBarLayoutCrudListConsumerScreen({
|
||||||
|
this.title,
|
||||||
|
this.currentIndex,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget parent(BuildContext context, Widget child) => AppBarLayout(
|
||||||
|
title: title ?? 'Title',
|
||||||
|
body: child,
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
// 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' as bloc_base;
|
||||||
|
import 'package:wyatt_bloc_layout/wyatt_bloc_layout.dart';
|
||||||
|
|
||||||
|
abstract class BottomNavigationBarLayoutCrudConsumerScreen<
|
||||||
|
Cubit extends bloc_base.Cubit<CrudState>,
|
||||||
|
T> extends CrudCubitConsumerScreen<Cubit, T> {
|
||||||
|
final int? currentIndex;
|
||||||
|
|
||||||
|
const BottomNavigationBarLayoutCrudConsumerScreen({
|
||||||
|
this.currentIndex,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget parent(BuildContext context, Widget child) =>
|
||||||
|
BottomNavigationBarLayout(
|
||||||
|
body: child,
|
||||||
|
currentIndex: currentIndex ?? 0,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class BottomNavigationBarLayoutCrudListConsumerScreen<
|
||||||
|
Cubit extends bloc_base.Cubit<CrudState>,
|
||||||
|
T> extends CrudListCubitConsumerScreen<Cubit, T> {
|
||||||
|
final String? title;
|
||||||
|
final int? currentIndex;
|
||||||
|
|
||||||
|
const BottomNavigationBarLayoutCrudListConsumerScreen({
|
||||||
|
this.title,
|
||||||
|
this.currentIndex,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget parent(BuildContext context, Widget child) =>
|
||||||
|
BottomNavigationBarLayout(
|
||||||
|
body: child,
|
||||||
|
currentIndex: currentIndex ?? 0,
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -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:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart' as bloc_base;
|
||||||
|
import 'package:wyatt_bloc_helper/wyatt_bloc_helper.dart';
|
||||||
|
import 'package:wyatt_crud_bloc/wyatt_crud_bloc.dart';
|
||||||
|
import 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart';
|
||||||
|
|
||||||
|
abstract class CrudCubitConsumerScreenBase<
|
||||||
|
Cubit extends bloc_base.Cubit<CrudState>,
|
||||||
|
SuccessState extends CrudSuccess>
|
||||||
|
extends CubitConsumerScreen<Cubit, CrudState> {
|
||||||
|
const CrudCubitConsumerScreenBase({super.key});
|
||||||
|
|
||||||
|
Widget errorBuilder(BuildContext context, CrudError state) =>
|
||||||
|
context.components.errorWidget?.configure(error: state.message) ??
|
||||||
|
const SizedBox.shrink();
|
||||||
|
|
||||||
|
Widget loadingBuilder(BuildContext context, CrudLoading state) =>
|
||||||
|
context.components.loadingWidget ?? const SizedBox.shrink();
|
||||||
|
|
||||||
|
Widget initialBuilder(BuildContext context, CrudInitial state) =>
|
||||||
|
const SizedBox.shrink();
|
||||||
|
|
||||||
|
Widget successBuilder(BuildContext context, SuccessState state);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget onBuild(BuildContext context, CrudState state) =>
|
||||||
|
CrudBuilder<CrudInitial, CrudLoading, SuccessState, CrudError>(
|
||||||
|
errorBuilder: errorBuilder,
|
||||||
|
loadingBuilder: loadingBuilder,
|
||||||
|
initialBuilder: initialBuilder,
|
||||||
|
state: state,
|
||||||
|
builder: successBuilder,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class CrudCubitConsumerScreen<Cubit extends bloc_base.Cubit<CrudState>,
|
||||||
|
T> extends CrudCubitConsumerScreenBase<Cubit, CrudLoaded<T>> {
|
||||||
|
const CrudCubitConsumerScreen();
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class CrudListCubitConsumerScreen<
|
||||||
|
Cubit extends bloc_base.Cubit<CrudState>,
|
||||||
|
T> extends CrudCubitConsumerScreenBase<Cubit, CrudListLoaded<T>> {
|
||||||
|
const CrudListCubitConsumerScreen();
|
||||||
|
}
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
// 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/src/widgets/framework.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart' as bloc_base;
|
||||||
|
import 'package:wyatt_bloc_layout/wyatt_bloc_layout.dart';
|
||||||
|
|
||||||
|
abstract class FrameLayoutCrudConsumerScreen<
|
||||||
|
Cubit extends bloc_base.Cubit<CrudState>,
|
||||||
|
T> extends CrudCubitConsumerScreen<Cubit, T> {
|
||||||
|
final String? title;
|
||||||
|
final int? currentIndex;
|
||||||
|
|
||||||
|
const FrameLayoutCrudConsumerScreen({
|
||||||
|
this.title,
|
||||||
|
this.currentIndex,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget parent(BuildContext context, Widget child) => FrameLayout(
|
||||||
|
title: title ?? 'Title',
|
||||||
|
body: child,
|
||||||
|
currentIndex: currentIndex ?? 0,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class FrameLayoutCrudListConsumerScreen<
|
||||||
|
Cubit extends bloc_base.Cubit<CrudState>,
|
||||||
|
T> extends CrudListCubitConsumerScreen<Cubit, T> {
|
||||||
|
final String? title;
|
||||||
|
final int? currentIndex;
|
||||||
|
|
||||||
|
const FrameLayoutCrudListConsumerScreen({
|
||||||
|
this.title,
|
||||||
|
this.currentIndex,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget parent(BuildContext context, Widget child) => FrameLayout(
|
||||||
|
title: title ?? 'Title',
|
||||||
|
body: child,
|
||||||
|
currentIndex: currentIndex ?? 0,
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
// 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/>.
|
||||||
|
|
||||||
|
export 'consumers/crud_cubit_consumer_screen_bases.dart';
|
||||||
|
export 'consumers/bottom_navigation_bar_layout_crud_consumer_screen.dart';
|
||||||
|
export 'consumers/app_bar_cubit_consumer_screen.dart';
|
||||||
|
export 'consumers/frame_layout_crud_consumer_screen.dart';
|
||||||
|
export 'screens/crud_cubit_screen_base.dart';
|
||||||
|
export 'screens/app_bar_cubit_screen.dart';
|
||||||
|
export 'screens/bottom_navigation_bar_layout_crud_screen.dart';
|
||||||
|
export 'screens/frame_layout_crud_screen.dart';
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
// 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' as bloc_base;
|
||||||
|
import 'package:wyatt_bloc_layout/wyatt_bloc_layout.dart';
|
||||||
|
|
||||||
|
abstract class AppBarLayoutCrudScreen<Cubit extends bloc_base.Cubit<CrudState>,
|
||||||
|
T> extends CrudCubitScreen<Cubit, T> {
|
||||||
|
final String? title;
|
||||||
|
|
||||||
|
const AppBarLayoutCrudScreen({
|
||||||
|
this.title,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget parent(BuildContext context, Widget child) => AppBarLayout(
|
||||||
|
title: title ?? 'Title',
|
||||||
|
body: child,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class AppBarLayoutCrudListScreen<
|
||||||
|
Cubit extends bloc_base.Cubit<CrudState>,
|
||||||
|
T> extends CrudListCubitScreen<Cubit, T> {
|
||||||
|
final String? title;
|
||||||
|
final int? currentIndex;
|
||||||
|
|
||||||
|
const AppBarLayoutCrudListScreen({
|
||||||
|
this.title,
|
||||||
|
this.currentIndex,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget parent(BuildContext context, Widget child) => AppBarLayout(
|
||||||
|
title: title ?? 'Title',
|
||||||
|
body: child,
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
// 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' as bloc_base;
|
||||||
|
import 'package:wyatt_bloc_layout/wyatt_bloc_layout.dart';
|
||||||
|
|
||||||
|
abstract class BottomNavigationBarLayoutCrudScreen<
|
||||||
|
Cubit extends bloc_base.Cubit<CrudState>,
|
||||||
|
T> extends CrudCubitScreen<Cubit, T> {
|
||||||
|
final int? currentIndex;
|
||||||
|
|
||||||
|
const BottomNavigationBarLayoutCrudScreen({
|
||||||
|
this.currentIndex,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget parent(BuildContext context, Widget child) =>
|
||||||
|
BottomNavigationBarLayout(
|
||||||
|
body: child,
|
||||||
|
currentIndex: currentIndex ?? 0,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class BottomNavigationBarLayoutCrudListScreen<
|
||||||
|
Cubit extends bloc_base.Cubit<CrudState>,
|
||||||
|
T> extends CrudListCubitScreen<Cubit, T> {
|
||||||
|
final String? title;
|
||||||
|
final int? currentIndex;
|
||||||
|
|
||||||
|
const BottomNavigationBarLayoutCrudListScreen({
|
||||||
|
this.title,
|
||||||
|
this.currentIndex,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget parent(BuildContext context, Widget child) =>
|
||||||
|
BottomNavigationBarLayout(
|
||||||
|
body: child,
|
||||||
|
currentIndex: currentIndex ?? 0,
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
// 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' as bloc_base;
|
||||||
|
import 'package:wyatt_bloc_layout/wyatt_bloc_layout.dart';
|
||||||
|
|
||||||
|
abstract class CrudCubitScreenBase<Cubit extends bloc_base.Cubit<CrudState>,
|
||||||
|
SuccessState extends CrudSuccess> extends CubitScreen<Cubit, CrudState> {
|
||||||
|
const CrudCubitScreenBase();
|
||||||
|
Widget errorBuilder(BuildContext context, CrudError state) =>
|
||||||
|
context.components.errorWidget?.configure(error: state.message) ??
|
||||||
|
const SizedBox.shrink();
|
||||||
|
|
||||||
|
Widget loadingBuilder(BuildContext context, CrudLoading state) =>
|
||||||
|
context.components.loadingWidget ?? const SizedBox.shrink();
|
||||||
|
|
||||||
|
Widget initialBuilder(BuildContext context, CrudInitial state) =>
|
||||||
|
const SizedBox.shrink();
|
||||||
|
|
||||||
|
Widget successBuilder(BuildContext context, SuccessState state);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget onBuild(BuildContext context, CrudState state) =>
|
||||||
|
CrudBuilder<CrudInitial, CrudLoading, SuccessState, CrudError>(
|
||||||
|
errorBuilder: errorBuilder,
|
||||||
|
loadingBuilder: loadingBuilder,
|
||||||
|
initialBuilder: initialBuilder,
|
||||||
|
state: state,
|
||||||
|
builder: successBuilder,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class CrudCubitScreen<Cubit extends bloc_base.Cubit<CrudState>, T>
|
||||||
|
extends CrudCubitScreenBase<Cubit, CrudLoaded<T>> {
|
||||||
|
const CrudCubitScreen();
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class CrudListCubitScreen<Cubit extends bloc_base.Cubit<CrudState>, T>
|
||||||
|
extends CrudCubitScreenBase<Cubit, CrudListLoaded<T>> {
|
||||||
|
const CrudListCubitScreen();
|
||||||
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
// 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/src/widgets/framework.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart' as bloc_base;
|
||||||
|
import 'package:wyatt_bloc_layout/wyatt_bloc_layout.dart';
|
||||||
|
|
||||||
|
abstract class FrameLayoutCrudScreen<Cubit extends bloc_base.Cubit<CrudState>,
|
||||||
|
T> extends CrudCubitScreen<Cubit, T> {
|
||||||
|
final String? title;
|
||||||
|
final int? currentIndex;
|
||||||
|
|
||||||
|
const FrameLayoutCrudScreen({
|
||||||
|
this.title,
|
||||||
|
this.currentIndex,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget parent(BuildContext context, Widget child) => FrameLayout(
|
||||||
|
title: title ?? 'Title',
|
||||||
|
body: child,
|
||||||
|
currentIndex: currentIndex ?? 0,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class FrameLayoutCrudListScreen<
|
||||||
|
Cubit extends bloc_base.Cubit<CrudState>,
|
||||||
|
T> extends CrudListCubitScreen<Cubit, T> {
|
||||||
|
final String? title;
|
||||||
|
final int? currentIndex;
|
||||||
|
|
||||||
|
const FrameLayoutCrudListScreen({
|
||||||
|
this.title,
|
||||||
|
this.currentIndex,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget parent(BuildContext context, Widget child) => FrameLayout(
|
||||||
|
title: title ?? 'Title',
|
||||||
|
body: child,
|
||||||
|
currentIndex: currentIndex ?? 0,
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -14,13 +14,10 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
library prompt.framework;
|
export 'presentation/presentation.dart';
|
||||||
|
|
||||||
import 'dart:io';
|
export 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:meta/meta.dart';
|
export 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart';
|
||||||
import 'package:wyatt_cli_toolbox/src/sequences/sequences.dart';
|
export 'package:wyatt_crud_bloc/wyatt_crud_bloc.dart';
|
||||||
import 'package:wyatt_cli_toolbox/src/stylish/stylish.dart';
|
export 'package:wyatt_ui_layout/wyatt_wyatt_ui_layout.dart';
|
||||||
|
export 'package:wyatt_bloc_helper/wyatt_bloc_helper.dart';
|
||||||
part 'build_context.dart';
|
|
||||||
part 'state.dart';
|
|
||||||
part 'widget.dart';
|
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
// 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/>.
|
||||||
|
|
||||||
|
/// Bloc Layout
|
||||||
|
library wyatt_bloc_layout;
|
||||||
|
|
||||||
|
export 'src/src.dart';
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
name: wyatt_bloc_layout
|
||||||
|
description: Layouts based on bloc helper library
|
||||||
|
repository: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages/src/branch/master/packages/wyatt_bloc_layout
|
||||||
|
version: 0.0.1
|
||||||
|
|
||||||
|
environment:
|
||||||
|
sdk: '>=2.17.0 <3.0.0'
|
||||||
|
|
||||||
|
dependencies:
|
||||||
|
|
||||||
|
flutter:
|
||||||
|
sdk: flutter
|
||||||
|
|
||||||
|
wyatt_bloc_helper:
|
||||||
|
git:
|
||||||
|
url: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages
|
||||||
|
path: packages/wyatt_bloc_helper
|
||||||
|
|
||||||
|
wyatt_ui_layout:
|
||||||
|
git:
|
||||||
|
url: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages
|
||||||
|
path: packages/wyatt_ui_layout
|
||||||
|
|
||||||
|
wyatt_crud_bloc:
|
||||||
|
git:
|
||||||
|
url: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages
|
||||||
|
path: packages/wyatt_crud_bloc
|
||||||
|
|
||||||
|
wyatt_ui_components:
|
||||||
|
git:
|
||||||
|
url: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages
|
||||||
|
path: packages/wyatt_ui_components
|
||||||
|
|
||||||
|
dev_dependencies:
|
||||||
|
|
||||||
|
flutter_test:
|
||||||
|
sdk: flutter
|
||||||
|
|
||||||
|
|
||||||
|
wyatt_analysis:
|
||||||
|
git:
|
||||||
|
url: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages
|
||||||
|
ref: wyatt_analysis-v2.3.0
|
||||||
|
path: packages/wyatt_analysis
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
# Files and directories created by pub.
|
|
||||||
.dart_tool/
|
|
||||||
.packages
|
|
||||||
|
|
||||||
# Conventional directory for build outputs.
|
|
||||||
build/
|
|
||||||
|
|
||||||
# Omit committing pubspec.lock for library packages; see
|
|
||||||
# https://dart.dev/guides/libraries/private-files#pubspeclock.
|
|
||||||
pubspec.lock
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
## 1.0.0
|
|
||||||
|
|
||||||
- Initial version.
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
include: package:wyatt_analysis/analysis_options.yaml
|
|
||||||
@@ -1,273 +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:io';
|
|
||||||
import 'dart:math';
|
|
||||||
|
|
||||||
import 'package:wyatt_cli_toolbox/wyatt_cli_toolbox.dart';
|
|
||||||
|
|
||||||
void testStylish() {
|
|
||||||
print('my beautiful text in magenta'.magenta());
|
|
||||||
print('you can combine multiple styles'.yellow().bgBlue().bold());
|
|
||||||
|
|
||||||
print('\x1B[36mstart style');
|
|
||||||
print('style continues on this line');
|
|
||||||
print('but not on this line'.reset());
|
|
||||||
|
|
||||||
print('\x1B[41mnot stripped\x1B[49m');
|
|
||||||
print('\x1B[41mstripped\x1B[49m'.strip());
|
|
||||||
|
|
||||||
Stylish.config(enable: false);
|
|
||||||
print('you can disable extension'.fg(r: 20, g: 160, b: 80));
|
|
||||||
Stylish.config(enable: true);
|
|
||||||
print('and reenable it on the fly'.fg(r: 20, g: 160, b: 80));
|
|
||||||
print('custom bg color'.bg(r: 80, g: 110, b: 30));
|
|
||||||
}
|
|
||||||
|
|
||||||
void testSequences() {
|
|
||||||
Sequences.clearEntireScreen();
|
|
||||||
print('Clear entire screen');
|
|
||||||
|
|
||||||
print('Hide cursor');
|
|
||||||
Sequences.hideCursor();
|
|
||||||
sleep(Duration(seconds: 1));
|
|
||||||
print('Unhide cursor');
|
|
||||||
Sequences.unhideCursor();
|
|
||||||
sleep(Duration(seconds: 1));
|
|
||||||
|
|
||||||
print('Save cursor position');
|
|
||||||
Sequences.savePosition();
|
|
||||||
sleep(Duration(seconds: 1));
|
|
||||||
|
|
||||||
print('Move cursor');
|
|
||||||
Sequences.moveCursor(6, 3);
|
|
||||||
sleep(Duration(seconds: 1));
|
|
||||||
|
|
||||||
Sequences.restorePosition();
|
|
||||||
Sequences.moveDown(1);
|
|
||||||
sleep(Duration(seconds: 1));
|
|
||||||
print('Restore cursor position');
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> testSpinners() async {
|
|
||||||
print('Starting computation 1...');
|
|
||||||
await Spinner.start(SpinnerType.fistBump);
|
|
||||||
sleep(Duration(seconds: 2));
|
|
||||||
Spinner.stop();
|
|
||||||
|
|
||||||
print('Starting computation 2...');
|
|
||||||
await Spinner.start(SpinnerType.dots5, text: 'Loading...');
|
|
||||||
sleep(Duration(seconds: 3));
|
|
||||||
Spinner.stop();
|
|
||||||
|
|
||||||
print('Starting computation 3...');
|
|
||||||
await Spinner.custom(
|
|
||||||
Indicator(
|
|
||||||
name: 'Eyes',
|
|
||||||
interval: 100,
|
|
||||||
frames: <String>['◡◡', '⊙⊙', '◠◠']
|
|
||||||
.map<String>((String e) => '\x1B[36m$e\x1B[39m')
|
|
||||||
.toList(),
|
|
||||||
label: 'Computing...',
|
|
||||||
),
|
|
||||||
);
|
|
||||||
await Future<void>.delayed(Duration(seconds: 2));
|
|
||||||
Spinner.stop();
|
|
||||||
|
|
||||||
print('Starting computation 4...');
|
|
||||||
await Spinner.start(SpinnerType.pipe, text: 'Linking...');
|
|
||||||
sleep(Duration(seconds: 3));
|
|
||||||
Spinner.update(
|
|
||||||
SpinnerType.circle.indicator.copyWith(label: 'Compiling...'),
|
|
||||||
);
|
|
||||||
sleep(Duration(seconds: 3));
|
|
||||||
Spinner.stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
void testPrompt() {
|
|
||||||
final Prompt pr = Prompt();
|
|
||||||
final StringQuestion q1 = StringQuestion(
|
|
||||||
"What's your name ?",
|
|
||||||
identifier: 'name',
|
|
||||||
);
|
|
||||||
final PasswordQuestion q8 = PasswordQuestion(
|
|
||||||
'Password ?',
|
|
||||||
comment: 'Secret shhht.',
|
|
||||||
identifier: 'password',
|
|
||||||
);
|
|
||||||
final NumberQuestion q7 = NumberQuestion(
|
|
||||||
'How old are you?',
|
|
||||||
identifier: 'age',
|
|
||||||
);
|
|
||||||
final BooleanQuestion q2 = BooleanQuestion(
|
|
||||||
'Do you like Dart ?',
|
|
||||||
identifier: 'dart',
|
|
||||||
);
|
|
||||||
final ListQuestion q3 = ListQuestion(
|
|
||||||
'Which target ?',
|
|
||||||
<String>['android', 'ios', 'windows', 'macos'],
|
|
||||||
identifier: 'platform',
|
|
||||||
);
|
|
||||||
final Message q4 = Message(
|
|
||||||
'Oh oh !',
|
|
||||||
level: MessageLevel.warn,
|
|
||||||
identifier: 'warn',
|
|
||||||
);
|
|
||||||
final Message q5 = Message(
|
|
||||||
'Oh damn :(',
|
|
||||||
level: MessageLevel.fail,
|
|
||||||
identifier: 'error',
|
|
||||||
);
|
|
||||||
final Message q6 = Message(
|
|
||||||
'Thank you, bye! 🤙',
|
|
||||||
comment: 'Pretty comment nah?',
|
|
||||||
identifier: 'bye',
|
|
||||||
);
|
|
||||||
|
|
||||||
pr
|
|
||||||
..addAll(<Question<dynamic>>[q1, q8, q7, q2, q3, q4, q5, q6])
|
|
||||||
..ask();
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> testWorkflow() async {
|
|
||||||
final Task<int> t1 = Task<int>(
|
|
||||||
name: 'Analyzing',
|
|
||||||
id: 'analyze',
|
|
||||||
spinner: SpinnerType.circle,
|
|
||||||
task: () {
|
|
||||||
return waitFor<int>(
|
|
||||||
Future<int>.delayed(Duration(seconds: 3), () => 13),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
onFinish: (Object? i) {
|
|
||||||
return '$i files analyzed';
|
|
||||||
},
|
|
||||||
);
|
|
||||||
final Task<int> t2 = Task<int>(
|
|
||||||
name: 'Formatting',
|
|
||||||
id: 'format',
|
|
||||||
spinner: SpinnerType.circle,
|
|
||||||
task: () {
|
|
||||||
return waitFor<int>(
|
|
||||||
Future<int>.delayed(Duration(seconds: 4), () => 1287),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
onFinish: (Object? i) {
|
|
||||||
return '$i files modified';
|
|
||||||
},
|
|
||||||
);
|
|
||||||
final Task<void> t3 = Task<void>(
|
|
||||||
name: 'Building',
|
|
||||||
id: 'build',
|
|
||||||
task: () {
|
|
||||||
final List<String> _tasks = <String>[
|
|
||||||
'main.c',
|
|
||||||
'crypto.c',
|
|
||||||
'workflow.c',
|
|
||||||
'wyatt.c',
|
|
||||||
'logger.c',
|
|
||||||
'task.c',
|
|
||||||
];
|
|
||||||
for (final String i in _tasks) {
|
|
||||||
Task.print(i);
|
|
||||||
sleep(Duration(seconds: Random().nextInt(4) + 1));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onFinish: (_) {
|
|
||||||
return 'Compilation success';
|
|
||||||
},
|
|
||||||
);
|
|
||||||
final Task<void> t4 = Task<void>(
|
|
||||||
name: 'Testing',
|
|
||||||
id: 'test',
|
|
||||||
task: () {
|
|
||||||
final List<String> _tasks = <String>[
|
|
||||||
'wyatt.h',
|
|
||||||
'crypto.h',
|
|
||||||
];
|
|
||||||
for (final String i in _tasks) {
|
|
||||||
Task.print(i);
|
|
||||||
sleep(Duration(seconds: Random().nextInt(3)));
|
|
||||||
}
|
|
||||||
throw Exception('An error occured during ${'test::crypto.h'.red()}');
|
|
||||||
},
|
|
||||||
onFinish: (_) {
|
|
||||||
return 'All tests passed';
|
|
||||||
},
|
|
||||||
onError: (Object e) {
|
|
||||||
return e.toString();
|
|
||||||
},
|
|
||||||
);
|
|
||||||
final Task<void> t5 = Task<void>(
|
|
||||||
name: 'Bundling',
|
|
||||||
id: 'bundle',
|
|
||||||
task: () {
|
|
||||||
sleep(Duration(seconds: 3));
|
|
||||||
throw SkipException('Bundle skipped.');
|
|
||||||
},
|
|
||||||
onFinish: (_) {
|
|
||||||
return 'Files generated in dist/';
|
|
||||||
},
|
|
||||||
onSkip: (SkipException e) {
|
|
||||||
return e.toString();
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
final Workflow w = await Workflow.create(<Task<dynamic>>[t1, t2, t3, t4, t5]);
|
|
||||||
w.start();
|
|
||||||
|
|
||||||
print('\n${w.results.toString().dim()}');
|
|
||||||
}
|
|
||||||
|
|
||||||
void testNewPrompt() {
|
|
||||||
final name = Input(message: 'Your name').prompt();
|
|
||||||
stdout.writeln(name);
|
|
||||||
|
|
||||||
final email = Input(
|
|
||||||
message: 'Your email',
|
|
||||||
validator: (String x) {
|
|
||||||
if (x.contains('@')) {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
throw ValidationError('Not a valid email');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
).prompt();
|
|
||||||
stdout.writeln(email);
|
|
||||||
|
|
||||||
final planet = Input(
|
|
||||||
message: 'Your planet',
|
|
||||||
defaultValue: 'Earth',
|
|
||||||
).prompt();
|
|
||||||
stdout.writeln(planet);
|
|
||||||
|
|
||||||
final galaxy = Input(
|
|
||||||
message: 'Your galaxy',
|
|
||||||
initialValue: 'Andromeda',
|
|
||||||
).prompt();
|
|
||||||
stdout.writeln(galaxy);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> main() async {
|
|
||||||
// sleep(Duration(seconds: 2));
|
|
||||||
// testPrompt();
|
|
||||||
// await testWorkflow();
|
|
||||||
// testStylish();
|
|
||||||
// testSequences();
|
|
||||||
// await testSpinners();
|
|
||||||
// testPrompt();
|
|
||||||
testNewPrompt();
|
|
||||||
}
|
|
||||||
@@ -1,60 +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:io';
|
|
||||||
|
|
||||||
import 'package:wyatt_cli_toolbox/src/prompt/question.dart';
|
|
||||||
import 'package:wyatt_cli_toolbox/src/sequences/sequences.dart';
|
|
||||||
import 'package:wyatt_cli_toolbox/src/stylish/stylish.dart';
|
|
||||||
|
|
||||||
class BooleanQuestion extends Question<bool> {
|
|
||||||
BooleanQuestion(
|
|
||||||
String question, {
|
|
||||||
this.defaultTo = false,
|
|
||||||
String? comment,
|
|
||||||
required String identifier,
|
|
||||||
}) : super(QuestionType.booleanQuestion, identifier, question, comment);
|
|
||||||
|
|
||||||
bool? answer;
|
|
||||||
final bool defaultTo;
|
|
||||||
|
|
||||||
@override
|
|
||||||
String formatComment() => (super.formatComment().trim().isEmpty)
|
|
||||||
? defaultTo
|
|
||||||
? ' (Y/n) '.dim()
|
|
||||||
: ' (y/N) '.dim()
|
|
||||||
: super.formatComment();
|
|
||||||
|
|
||||||
@override
|
|
||||||
bool ask() {
|
|
||||||
stdout.write(formatQuestion());
|
|
||||||
String input = '';
|
|
||||||
input = stdin.readLineSync(encoding: utf8)!.trim();
|
|
||||||
stdout.write(Sequences.escMoveUp(1) + formatQuestion());
|
|
||||||
if (input.isEmpty) {
|
|
||||||
answer = defaultTo;
|
|
||||||
} else {
|
|
||||||
answer = input[0] == 'y' || input[0] == 'Y';
|
|
||||||
}
|
|
||||||
String replaceStr =
|
|
||||||
'\r${formatQuestion()}${Sequences.escClearLineFromCursorToEnd()}';
|
|
||||||
replaceStr += answer! ? 'Yes'.blue() : 'No'.blue();
|
|
||||||
stdout.writeln(replaceStr);
|
|
||||||
|
|
||||||
return answer!;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,49 +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:io';
|
|
||||||
|
|
||||||
import 'package:wyatt_cli_toolbox/src/sequences/sequences.dart';
|
|
||||||
import 'package:wyatt_cli_toolbox/src/stylish/stylish.dart';
|
|
||||||
|
|
||||||
/// Abstract class providing XTerm escape sequences
|
|
||||||
abstract class Control {
|
|
||||||
/// Use Squences.escMoveUp, concatenate your string ([str])
|
|
||||||
/// and then blank the remaining line.
|
|
||||||
static String replacePreviousLine(String str) =>
|
|
||||||
Sequences.escMoveUp(1) + str + Sequences.escClearLineFromCursorToEnd();
|
|
||||||
|
|
||||||
/// Reset XTerm sequence.
|
|
||||||
/// This is always applied after using some other sequence.
|
|
||||||
static String reset = ''.reset();
|
|
||||||
|
|
||||||
/// See: https://codepoints.net/dingbats
|
|
||||||
static String questionIndicator() => '?'.green();
|
|
||||||
|
|
||||||
static String exclamationIndicator() => '!'.yellow();
|
|
||||||
|
|
||||||
static String infoIndicator() =>
|
|
||||||
Platform.isWindows ? 'i'.cyan() : '\u2139'.cyan();
|
|
||||||
|
|
||||||
static String rightIndicator() =>
|
|
||||||
Platform.isWindows ? '>'.blue() : '\u276F'.blue();
|
|
||||||
|
|
||||||
static String validIndicator() =>
|
|
||||||
Platform.isWindows ? 'v'.green() : '\u2714'.green();
|
|
||||||
|
|
||||||
static String wrongIndicator() =>
|
|
||||||
Platform.isWindows ? 'x'.red() : '\u2718'.red();
|
|
||||||
}
|
|
||||||
@@ -1,95 +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/>.
|
|
||||||
|
|
||||||
part of prompt.framework;
|
|
||||||
|
|
||||||
class BuildContext {
|
|
||||||
int _buildCount = 0;
|
|
||||||
int get buildCount => _buildCount;
|
|
||||||
void incrementBuildCount() => _buildCount++;
|
|
||||||
void resetBuildCount() => _buildCount = 0;
|
|
||||||
|
|
||||||
int _lineCount = 0;
|
|
||||||
int get lineCount => _lineCount;
|
|
||||||
void incrementLineCount() => _lineCount++;
|
|
||||||
void resetLineCount() => _lineCount = 0;
|
|
||||||
|
|
||||||
static void reset() {
|
|
||||||
Sequences.unhideCursor();
|
|
||||||
Sequences.write(''.reset());
|
|
||||||
}
|
|
||||||
|
|
||||||
void hideCursor() {
|
|
||||||
Sequences.hideCursor();
|
|
||||||
}
|
|
||||||
|
|
||||||
void showCursor() {
|
|
||||||
Sequences.unhideCursor();
|
|
||||||
}
|
|
||||||
|
|
||||||
void write(String text) {
|
|
||||||
Sequences.write(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
void writeln(String text) {
|
|
||||||
incrementLineCount();
|
|
||||||
Sequences.writeln(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
void erasePreviousLine([int n = 1]) {
|
|
||||||
for (int i = 0; i < n; i++) {
|
|
||||||
Sequences.moveUp(1);
|
|
||||||
Sequences.clearEntireLine();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void wipe() {
|
|
||||||
erasePreviousLine(lineCount);
|
|
||||||
resetLineCount();
|
|
||||||
}
|
|
||||||
|
|
||||||
int readKey() => stdin.readByteSync();
|
|
||||||
|
|
||||||
String readLine({
|
|
||||||
String initialValue = '',
|
|
||||||
}) {
|
|
||||||
var buffer = initialValue;
|
|
||||||
var index = buffer.length;
|
|
||||||
|
|
||||||
Sequences.savePosition();
|
|
||||||
|
|
||||||
if (buffer.isNotEmpty) {
|
|
||||||
write(buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
final key = readKey();
|
|
||||||
if (index == buffer.length) {
|
|
||||||
buffer += String.fromCharCode(key);
|
|
||||||
index++;
|
|
||||||
} else {
|
|
||||||
buffer = buffer.substring(0, index) +
|
|
||||||
String.fromCharCode(key) +
|
|
||||||
buffer.substring(index);
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
|
|
||||||
Sequences.restorePosition();
|
|
||||||
Sequences.clearLineFromCursorToEnd();
|
|
||||||
write(buffer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,150 +0,0 @@
|
|||||||
// 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 'dart:io';
|
|
||||||
|
|
||||||
import 'package:wyatt_cli_toolbox/src/spinners/spinners.dart';
|
|
||||||
import 'package:wyatt_cli_toolbox/src/stylish/stylish.dart';
|
|
||||||
|
|
||||||
typedef StyleFunction = String Function(String);
|
|
||||||
|
|
||||||
class Theme {
|
|
||||||
final String inputPrefix;
|
|
||||||
final String inputSuffix;
|
|
||||||
final String successPrefix;
|
|
||||||
final String successSuffix;
|
|
||||||
final String errorPrefix;
|
|
||||||
final String hiddenPrefix;
|
|
||||||
final StyleFunction messageStyle;
|
|
||||||
final StyleFunction errorStyle;
|
|
||||||
final StyleFunction hintStyle;
|
|
||||||
final StyleFunction valueStyle;
|
|
||||||
final StyleFunction defaultStyle;
|
|
||||||
|
|
||||||
final String activeItemPrefix;
|
|
||||||
final String inactiveItemPrefix;
|
|
||||||
final StyleFunction activeItemStyle;
|
|
||||||
final StyleFunction inactiveItemStyle;
|
|
||||||
|
|
||||||
final String checkedItemPrefix;
|
|
||||||
final String uncheckedItemPrefix;
|
|
||||||
|
|
||||||
final String pickedItemPrefix;
|
|
||||||
final String unpickedItemPrefix;
|
|
||||||
|
|
||||||
final bool showActiveCursor;
|
|
||||||
|
|
||||||
final SpinnerType spinner;
|
|
||||||
|
|
||||||
const Theme({
|
|
||||||
required this.inputPrefix,
|
|
||||||
required this.inputSuffix,
|
|
||||||
required this.successPrefix,
|
|
||||||
required this.successSuffix,
|
|
||||||
required this.errorPrefix,
|
|
||||||
required this.hiddenPrefix,
|
|
||||||
required this.messageStyle,
|
|
||||||
required this.errorStyle,
|
|
||||||
required this.hintStyle,
|
|
||||||
required this.valueStyle,
|
|
||||||
required this.defaultStyle,
|
|
||||||
required this.activeItemPrefix,
|
|
||||||
required this.inactiveItemPrefix,
|
|
||||||
required this.activeItemStyle,
|
|
||||||
required this.inactiveItemStyle,
|
|
||||||
required this.checkedItemPrefix,
|
|
||||||
required this.uncheckedItemPrefix,
|
|
||||||
required this.pickedItemPrefix,
|
|
||||||
required this.unpickedItemPrefix,
|
|
||||||
required this.showActiveCursor,
|
|
||||||
required this.spinner,
|
|
||||||
});
|
|
||||||
|
|
||||||
Theme copyWith({
|
|
||||||
String? inputPrefix,
|
|
||||||
String? inputSuffix,
|
|
||||||
String? successPrefix,
|
|
||||||
String? successSuffix,
|
|
||||||
String? errorPrefix,
|
|
||||||
String? hiddenPrefix,
|
|
||||||
StyleFunction? messageStyle,
|
|
||||||
StyleFunction? errorStyle,
|
|
||||||
StyleFunction? hintStyle,
|
|
||||||
StyleFunction? valueStyle,
|
|
||||||
StyleFunction? defaultStyle,
|
|
||||||
String? activeItemPrefix,
|
|
||||||
String? inactiveItemPrefix,
|
|
||||||
StyleFunction? activeItemStyle,
|
|
||||||
StyleFunction? inactiveItemStyle,
|
|
||||||
String? checkedItemPrefix,
|
|
||||||
String? uncheckedItemPrefix,
|
|
||||||
String? pickedItemPrefix,
|
|
||||||
String? unpickedItemPrefix,
|
|
||||||
bool? showActiveCursor,
|
|
||||||
SpinnerType? spinner,
|
|
||||||
}) {
|
|
||||||
return Theme(
|
|
||||||
inputPrefix: inputPrefix ?? this.inputPrefix,
|
|
||||||
inputSuffix: inputSuffix ?? this.inputSuffix,
|
|
||||||
successPrefix: successPrefix ?? this.successPrefix,
|
|
||||||
successSuffix: successSuffix ?? this.successSuffix,
|
|
||||||
errorPrefix: errorPrefix ?? this.errorPrefix,
|
|
||||||
hiddenPrefix: hiddenPrefix ?? this.hiddenPrefix,
|
|
||||||
messageStyle: messageStyle ?? this.messageStyle,
|
|
||||||
errorStyle: errorStyle ?? this.errorStyle,
|
|
||||||
hintStyle: hintStyle ?? this.hintStyle,
|
|
||||||
valueStyle: valueStyle ?? this.valueStyle,
|
|
||||||
defaultStyle: defaultStyle ?? this.defaultStyle,
|
|
||||||
activeItemPrefix: activeItemPrefix ?? this.activeItemPrefix,
|
|
||||||
inactiveItemPrefix: inactiveItemPrefix ?? this.inactiveItemPrefix,
|
|
||||||
activeItemStyle: activeItemStyle ?? this.activeItemStyle,
|
|
||||||
inactiveItemStyle: inactiveItemStyle ?? this.inactiveItemStyle,
|
|
||||||
checkedItemPrefix: checkedItemPrefix ?? this.checkedItemPrefix,
|
|
||||||
uncheckedItemPrefix: uncheckedItemPrefix ?? this.uncheckedItemPrefix,
|
|
||||||
pickedItemPrefix: pickedItemPrefix ?? this.pickedItemPrefix,
|
|
||||||
unpickedItemPrefix: unpickedItemPrefix ?? this.unpickedItemPrefix,
|
|
||||||
showActiveCursor: showActiveCursor ?? this.showActiveCursor,
|
|
||||||
spinner: spinner ?? this.spinner,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
static Theme defaultTheme = colorfulTheme;
|
|
||||||
|
|
||||||
static final colorfulTheme = Theme(
|
|
||||||
inputPrefix: '?'.padRight(2).green(),
|
|
||||||
inputSuffix: (Platform.isWindows ? '>' : '\u276F').padLeft(2).grey(),
|
|
||||||
successPrefix: (Platform.isWindows ? 'v' : '\u2714').padRight(2).green(),
|
|
||||||
successSuffix: '•'.padLeft(2).grey(),
|
|
||||||
errorPrefix: (Platform.isWindows ? 'x' : '\u2718').padRight(2).red(),
|
|
||||||
hiddenPrefix: '*****',
|
|
||||||
messageStyle: (String message) => message.bold(),
|
|
||||||
errorStyle: (String error) => error.red(),
|
|
||||||
hintStyle: (String hint) => '($hint)'.grey(),
|
|
||||||
valueStyle: (String value) => value.green(),
|
|
||||||
defaultStyle: (String value) => value.cyan(),
|
|
||||||
activeItemPrefix: (Platform.isWindows ? '>' : '\u276F').green(),
|
|
||||||
inactiveItemPrefix: ' ',
|
|
||||||
activeItemStyle: (String item) => item.cyan(),
|
|
||||||
inactiveItemStyle: (String item) => item,
|
|
||||||
checkedItemPrefix: (Platform.isWindows ? 'v' : '\u2714').green(),
|
|
||||||
uncheckedItemPrefix: ' ',
|
|
||||||
pickedItemPrefix: (Platform.isWindows ? '>' : '\u276F').green(),
|
|
||||||
unpickedItemPrefix: ' ',
|
|
||||||
showActiveCursor: false,
|
|
||||||
spinner: SpinnerType.arrow,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,46 +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/>.
|
|
||||||
|
|
||||||
part of prompt.framework;
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,56 +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/>.
|
|
||||||
|
|
||||||
// ignore_for_file: constant_identifier_names
|
|
||||||
|
|
||||||
import 'dart:io';
|
|
||||||
|
|
||||||
const int ARROW_UP = 65;
|
|
||||||
const int ARROW_DOWN = 66;
|
|
||||||
const int ENTER = 10;
|
|
||||||
const int SPACE = 32;
|
|
||||||
|
|
||||||
const int WIN_UP = 119;
|
|
||||||
const int WIN_DOWN = 115;
|
|
||||||
const int WIN_ENTER = 13;
|
|
||||||
const int WIN_SPACE = 20;
|
|
||||||
|
|
||||||
/// Abstract class providing some key codes which can be statically accessed.
|
|
||||||
abstract class Keys {
|
|
||||||
/// Arrow down. Consists of three bytes.
|
|
||||||
/// For historical reasons, you can also use 's'
|
|
||||||
/// instead of arrow down on Windows.
|
|
||||||
///
|
|
||||||
/// It is packed into a single element list in
|
|
||||||
/// order to not break the spread syntax.
|
|
||||||
static final List<int> arrowDown =
|
|
||||||
Platform.isWindows ? <int>[WIN_DOWN] : <int>[27, 91, 66];
|
|
||||||
|
|
||||||
/// Arrows up. Consists of three bytes in Unix like systems (including MacOS).
|
|
||||||
/// For historical reasons, you can also use 'w' insted of arrow
|
|
||||||
/// up on Windows.
|
|
||||||
///
|
|
||||||
/// It is packed into a single element list in
|
|
||||||
/// order to not break the spread syntax.
|
|
||||||
static final List<int> arrowUp =
|
|
||||||
Platform.isWindows ? <int>[WIN_UP] : <int>[27, 91, 65];
|
|
||||||
|
|
||||||
/// Enter key. Single byte.
|
|
||||||
static final int enter = Platform.isWindows ? WIN_ENTER : ENTER;
|
|
||||||
|
|
||||||
/// Space key. Single byte.
|
|
||||||
static final int space = Platform.isWindows ? WIN_SPACE : SPACE;
|
|
||||||
}
|
|
||||||
@@ -1,129 +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:io';
|
|
||||||
|
|
||||||
import 'package:wyatt_cli_toolbox/src/prompt/control.dart';
|
|
||||||
import 'package:wyatt_cli_toolbox/src/prompt/keys.dart';
|
|
||||||
import 'package:wyatt_cli_toolbox/src/sequences/sequences.dart';
|
|
||||||
import 'package:wyatt_cli_toolbox/src/stylish/stylish.dart';
|
|
||||||
|
|
||||||
class ListChooser {
|
|
||||||
ListChooser(this.options) {
|
|
||||||
if (stdin.hasTerminal) {
|
|
||||||
// lineMode must be true to set echoMode in Windows
|
|
||||||
// see https://github.com/dart-lang/sdk/issues/28599
|
|
||||||
stdin.echoMode = false;
|
|
||||||
stdin.lineMode = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
List<String> options;
|
|
||||||
|
|
||||||
String choose() {
|
|
||||||
int input;
|
|
||||||
int index = 0;
|
|
||||||
|
|
||||||
_renderList(0, initial: true);
|
|
||||||
|
|
||||||
while ((input = _userInput()) != ENTER) {
|
|
||||||
if (input == ARROW_UP) {
|
|
||||||
if (index > 0) {
|
|
||||||
index--;
|
|
||||||
}
|
|
||||||
} else if (input == ARROW_DOWN) {
|
|
||||||
if (index < options.length - 1) {
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_renderList(index);
|
|
||||||
}
|
|
||||||
_resetStdin();
|
|
||||||
return options[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
void _deletePreviousList() {
|
|
||||||
for (int i = 0; i < options.length; i++) {
|
|
||||||
Sequences.write(
|
|
||||||
Sequences.escMoveUp(1) + Sequences.escClearLineFromCursorToEnd(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void _renderList(int index, {bool initial = false}) {
|
|
||||||
if (!initial) {
|
|
||||||
_deletePreviousList();
|
|
||||||
}
|
|
||||||
for (int i = 0; i < options.length; i++) {
|
|
||||||
if (i == index) {
|
|
||||||
stdout.writeln('${Control.rightIndicator()} ${options[i].blue()}');
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
stdout.writeln(' ${options[i]}');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void _resetStdin() {
|
|
||||||
if (stdin.hasTerminal) {
|
|
||||||
// Order is important here
|
|
||||||
stdin.lineMode = true;
|
|
||||||
stdin.echoMode = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(hpcl): improve keycode parsing for multiple bytes codes
|
|
||||||
int _userInput() {
|
|
||||||
final int navigationResult = stdin.readByteSync();
|
|
||||||
if (navigationResult < 0) {
|
|
||||||
return navigationResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Platform.isWindows) {
|
|
||||||
if (navigationResult == Keys.enter) {
|
|
||||||
return ENTER;
|
|
||||||
}
|
|
||||||
if (navigationResult == Keys.space) {
|
|
||||||
return SPACE;
|
|
||||||
}
|
|
||||||
if (navigationResult == Keys.arrowUp[0]) {
|
|
||||||
return ARROW_UP;
|
|
||||||
}
|
|
||||||
if (navigationResult == Keys.arrowDown[0]) {
|
|
||||||
return ARROW_DOWN;
|
|
||||||
} else {
|
|
||||||
return navigationResult;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (navigationResult == ENTER) {
|
|
||||||
return ENTER;
|
|
||||||
}
|
|
||||||
if (navigationResult == SPACE) {
|
|
||||||
return SPACE;
|
|
||||||
}
|
|
||||||
|
|
||||||
final int anotherByte = stdin.readByteSync();
|
|
||||||
if (anotherByte == ENTER) {
|
|
||||||
return ENTER;
|
|
||||||
}
|
|
||||||
if (anotherByte == SPACE) {
|
|
||||||
return SPACE;
|
|
||||||
}
|
|
||||||
|
|
||||||
final int input = stdin.readByteSync();
|
|
||||||
return input;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,47 +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:io';
|
|
||||||
|
|
||||||
import 'package:wyatt_cli_toolbox/src/prompt/list_chooser.dart';
|
|
||||||
import 'package:wyatt_cli_toolbox/src/prompt/question.dart';
|
|
||||||
import 'package:wyatt_cli_toolbox/src/stylish/stylish.dart';
|
|
||||||
|
|
||||||
class ListQuestion extends Question<String> {
|
|
||||||
ListQuestion(
|
|
||||||
String question,
|
|
||||||
this.options, {
|
|
||||||
String? comment,
|
|
||||||
required String identifier,
|
|
||||||
}) : super(QuestionType.listQuestion, identifier, question, comment);
|
|
||||||
|
|
||||||
List<String> options;
|
|
||||||
String? answer;
|
|
||||||
|
|
||||||
@override
|
|
||||||
String formatComment() => (super.formatComment().trim().isEmpty)
|
|
||||||
? ' (User arrow keys) '.dim()
|
|
||||||
: super.formatComment();
|
|
||||||
|
|
||||||
@override
|
|
||||||
String ask() {
|
|
||||||
stdout.writeln(formatQuestion());
|
|
||||||
final ListChooser chooser = ListChooser(options);
|
|
||||||
final String input = chooser.choose();
|
|
||||||
answer = input;
|
|
||||||
return input;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,54 +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:io';
|
|
||||||
|
|
||||||
import 'package:wyatt_cli_toolbox/src/prompt/control.dart';
|
|
||||||
import 'package:wyatt_cli_toolbox/src/prompt/question.dart';
|
|
||||||
|
|
||||||
enum MessageLevel { debug, info, success, warn, fail }
|
|
||||||
|
|
||||||
class Message extends Question<void> {
|
|
||||||
Message(
|
|
||||||
String text, {
|
|
||||||
String? comment,
|
|
||||||
this.level = MessageLevel.info,
|
|
||||||
required String identifier,
|
|
||||||
}) : super(QuestionType.message, identifier, text, comment);
|
|
||||||
|
|
||||||
MessageLevel level;
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get prefix {
|
|
||||||
switch (level) {
|
|
||||||
case MessageLevel.debug:
|
|
||||||
return ' ';
|
|
||||||
case MessageLevel.info:
|
|
||||||
return Control.infoIndicator();
|
|
||||||
case MessageLevel.success:
|
|
||||||
return Control.validIndicator();
|
|
||||||
case MessageLevel.warn:
|
|
||||||
return Control.exclamationIndicator();
|
|
||||||
case MessageLevel.fail:
|
|
||||||
return Control.wrongIndicator();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void ask() {
|
|
||||||
stdout.writeln(formatQuestion());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,57 +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:io';
|
|
||||||
|
|
||||||
import 'package:wyatt_cli_toolbox/src/prompt/question.dart';
|
|
||||||
import 'package:wyatt_cli_toolbox/src/sequences/sequences.dart';
|
|
||||||
import 'package:wyatt_cli_toolbox/src/stylish/stylish.dart';
|
|
||||||
|
|
||||||
class NumberQuestion extends Question<num> {
|
|
||||||
NumberQuestion(String question, {String? comment, required String identifier})
|
|
||||||
: super(QuestionType.stringQuestion, identifier, question, comment);
|
|
||||||
|
|
||||||
num? answer;
|
|
||||||
|
|
||||||
@override
|
|
||||||
String formatComment() => (super.formatComment().trim().isEmpty)
|
|
||||||
? ' Mandatory! '.dim()
|
|
||||||
: super.formatComment();
|
|
||||||
|
|
||||||
@override
|
|
||||||
num ask() {
|
|
||||||
stdout.write(formatQuestion());
|
|
||||||
String input = '';
|
|
||||||
bool valid = false;
|
|
||||||
num answer = 0;
|
|
||||||
while (!valid) {
|
|
||||||
input = stdin.readLineSync(encoding: utf8)!.trim();
|
|
||||||
try {
|
|
||||||
valid = input.isNotEmpty;
|
|
||||||
answer = num.parse(input);
|
|
||||||
} catch (e) {
|
|
||||||
valid = false;
|
|
||||||
}
|
|
||||||
stdout.write(Sequences.escMoveUp(1) + formatQuestion());
|
|
||||||
}
|
|
||||||
stdout.writeln(
|
|
||||||
// ignore: lines_longer_than_80_chars
|
|
||||||
'\r${formatQuestion()}${answer.toString().blue()}${Sequences.escClearLineFromCursorToEnd()}',
|
|
||||||
);
|
|
||||||
return answer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,66 +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:io';
|
|
||||||
|
|
||||||
import 'package:wyatt_cli_toolbox/src/prompt/keys.dart';
|
|
||||||
import 'package:wyatt_cli_toolbox/src/prompt/question.dart';
|
|
||||||
import 'package:wyatt_cli_toolbox/src/sequences/sequences.dart';
|
|
||||||
import 'package:wyatt_cli_toolbox/src/stylish/stylish.dart';
|
|
||||||
|
|
||||||
class PasswordQuestion extends Question<String> {
|
|
||||||
PasswordQuestion(
|
|
||||||
String question, {
|
|
||||||
String? comment,
|
|
||||||
required String identifier,
|
|
||||||
}) : super(QuestionType.passwordQuestion, identifier, question, comment);
|
|
||||||
|
|
||||||
String? answer;
|
|
||||||
|
|
||||||
@override
|
|
||||||
String ask() {
|
|
||||||
if (stdin.hasTerminal) {
|
|
||||||
stdin.echoMode = false;
|
|
||||||
stdin.lineMode = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
stdout.write(formatQuestion());
|
|
||||||
String input = '';
|
|
||||||
final List<int> bytes = <int>[];
|
|
||||||
|
|
||||||
int lastB = stdin.readByteSync();
|
|
||||||
while (lastB != Keys.enter) {
|
|
||||||
stdout.write('*');
|
|
||||||
bytes.add(lastB);
|
|
||||||
lastB = stdin.readByteSync();
|
|
||||||
}
|
|
||||||
input = utf8.decode(bytes);
|
|
||||||
stdout.write(formatQuestion());
|
|
||||||
answer = List<String>.generate(input.length, (_) => '*')
|
|
||||||
.reduce((String value, String element) => '$value$element');
|
|
||||||
stdout.writeln(
|
|
||||||
// ignore: lines_longer_than_80_chars
|
|
||||||
'\r${formatQuestion()}${answer!.blue()}${Sequences.escClearLineFromCursorToEnd()}',
|
|
||||||
);
|
|
||||||
|
|
||||||
if (stdin.hasTerminal) {
|
|
||||||
stdin.lineMode = true;
|
|
||||||
stdin.echoMode = true;
|
|
||||||
}
|
|
||||||
return input;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,66 +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 'package:wyatt_cli_toolbox/src/prompt/question.dart';
|
|
||||||
|
|
||||||
export 'boolean_question.dart';
|
|
||||||
export 'framework/framework.dart';
|
|
||||||
export 'framework/theme.dart';
|
|
||||||
export 'list_question.dart';
|
|
||||||
export 'message.dart';
|
|
||||||
export 'number_question.dart';
|
|
||||||
export 'password_question.dart';
|
|
||||||
export 'question.dart';
|
|
||||||
export 'string_question.dart';
|
|
||||||
export 'widgets/input.dart';
|
|
||||||
|
|
||||||
class Prompt {
|
|
||||||
Prompt({this.questions});
|
|
||||||
|
|
||||||
Map<String, dynamic> answers = <String, dynamic>{};
|
|
||||||
List<Question<dynamic>>? questions;
|
|
||||||
|
|
||||||
void add(Question<dynamic> question) {
|
|
||||||
if (questions != null) {
|
|
||||||
questions!.add(question);
|
|
||||||
} else {
|
|
||||||
questions = <Question<dynamic>>[question];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void addAll(List<Question<dynamic>> questions) {
|
|
||||||
if (this.questions != null) {
|
|
||||||
this.questions!.addAll(questions);
|
|
||||||
} else {
|
|
||||||
this.questions = questions;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Map<String, dynamic> ask() {
|
|
||||||
if (questions != null) {
|
|
||||||
for (final Question<dynamic> question in questions!) {
|
|
||||||
if (!(question.type == QuestionType.message)) {
|
|
||||||
answers[question.identifier] = question.ask();
|
|
||||||
} else {
|
|
||||||
question.ask();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
throw Exception('You must add questions before asking for prompt.');
|
|
||||||
}
|
|
||||||
return answers;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,43 +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:io';
|
|
||||||
|
|
||||||
import 'package:wyatt_cli_toolbox/src/prompt/question.dart';
|
|
||||||
import 'package:wyatt_cli_toolbox/src/sequences/sequences.dart';
|
|
||||||
import 'package:wyatt_cli_toolbox/src/stylish/stylish.dart';
|
|
||||||
|
|
||||||
class StringQuestion extends Question<String> {
|
|
||||||
StringQuestion(String question, {String? comment, required String identifier})
|
|
||||||
: super(QuestionType.stringQuestion, identifier, question, comment);
|
|
||||||
|
|
||||||
String? answer;
|
|
||||||
|
|
||||||
@override
|
|
||||||
String ask() {
|
|
||||||
stdout.write(formatQuestion());
|
|
||||||
String input = '';
|
|
||||||
input = stdin.readLineSync(encoding: utf8)!.trim();
|
|
||||||
stdout.write(Sequences.escMoveUp(1) + formatQuestion());
|
|
||||||
answer = input;
|
|
||||||
stdout.writeln(
|
|
||||||
// ignore: lines_longer_than_80_chars
|
|
||||||
'\r${formatQuestion()}${answer!.blue()}${Sequences.escClearLineFromCursorToEnd()}',
|
|
||||||
);
|
|
||||||
return input;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,134 +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 'package:wyatt_cli_toolbox/src/prompt/framework/framework.dart';
|
|
||||||
import 'package:wyatt_cli_toolbox/src/prompt/framework/theme.dart';
|
|
||||||
|
|
||||||
class Input extends Widget<String> {
|
|
||||||
final String message;
|
|
||||||
final String initialValue;
|
|
||||||
final String? defaultValue;
|
|
||||||
final bool Function(String)? validator;
|
|
||||||
final Theme theme;
|
|
||||||
|
|
||||||
Input({
|
|
||||||
required this.message,
|
|
||||||
this.initialValue = '',
|
|
||||||
this.defaultValue,
|
|
||||||
this.validator,
|
|
||||||
}) : theme = Theme.defaultTheme;
|
|
||||||
|
|
||||||
Input.withTheme({
|
|
||||||
required this.message,
|
|
||||||
required this.theme,
|
|
||||||
this.initialValue = '',
|
|
||||||
this.defaultValue,
|
|
||||||
this.validator,
|
|
||||||
});
|
|
||||||
|
|
||||||
String promptInput({
|
|
||||||
required String message,
|
|
||||||
String? hint,
|
|
||||||
}) {
|
|
||||||
final buffer = StringBuffer()
|
|
||||||
..write(theme.inputPrefix)
|
|
||||||
..write(theme.messageStyle(message));
|
|
||||||
if (hint != null) {
|
|
||||||
buffer
|
|
||||||
..write(' ')
|
|
||||||
..write(theme.hintStyle(hint));
|
|
||||||
}
|
|
||||||
buffer
|
|
||||||
..write(theme.inputSuffix)
|
|
||||||
..write(' ');
|
|
||||||
return buffer.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
String promptError({
|
|
||||||
required String message,
|
|
||||||
}) {
|
|
||||||
final buffer = StringBuffer()
|
|
||||||
..write(theme.errorPrefix)
|
|
||||||
..write(theme.errorStyle(message));
|
|
||||||
|
|
||||||
return buffer.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
State<Input> createState() => _InputState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _InputState extends State<Input> {
|
|
||||||
String? _value;
|
|
||||||
String? _error;
|
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
super.initState();
|
|
||||||
_value = widget.initialValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void dispose() {
|
|
||||||
if (_value != null) {
|
|
||||||
// TODO(hpcl): print success
|
|
||||||
}
|
|
||||||
super.dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void build() {
|
|
||||||
if (_error != null) {
|
|
||||||
context.writeln(widget.promptError(message: _error!));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
String prompt() {
|
|
||||||
while (true) {
|
|
||||||
context.write(
|
|
||||||
widget.promptInput(
|
|
||||||
message: widget.message,
|
|
||||||
hint: widget.defaultValue,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
final input = context.readLine(initialValue: widget.initialValue);
|
|
||||||
final line = input.isEmpty && widget.defaultValue != null
|
|
||||||
? widget.defaultValue!
|
|
||||||
: input;
|
|
||||||
if (widget.validator != null) {
|
|
||||||
try {
|
|
||||||
widget.validator!(line);
|
|
||||||
} on ValidationError catch (e) {
|
|
||||||
setState(() {
|
|
||||||
_error = e.message;
|
|
||||||
});
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
setState(() {
|
|
||||||
_value = line;
|
|
||||||
});
|
|
||||||
return _value!;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class ValidationError implements Exception {
|
|
||||||
final String message;
|
|
||||||
|
|
||||||
ValidationError(this.message);
|
|
||||||
}
|
|
||||||
@@ -1,155 +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:io';
|
|
||||||
|
|
||||||
/// Abstract class providing some useful ANSI escape sequences
|
|
||||||
abstract class Sequences {
|
|
||||||
/// Clear screen (Raw Sequence) `\x1B[J`
|
|
||||||
static String escClearScreen() => '\x1B[J';
|
|
||||||
|
|
||||||
/// Clear screen from cursor to end (Raw Sequence) `\x1B[0J`
|
|
||||||
static String escClearScreenFromCursorToEnd() => '\x1B[0J';
|
|
||||||
|
|
||||||
/// Clear screen from cursor to start (Raw Sequence) `\x1B[1J`
|
|
||||||
static String escClearScreenFromCursorToStart() => '\x1B[1J';
|
|
||||||
|
|
||||||
/// Clear entire screen (Raw Sequence) `\x1B[2J`
|
|
||||||
static String escClearEntireScreen() => '\x1B[2J';
|
|
||||||
|
|
||||||
/// Clear line (Raw Sequence) `\x1B[K`
|
|
||||||
static String escClearLine() => '\x1B[K';
|
|
||||||
|
|
||||||
/// Clear line from cursor to end (Raw Sequence) `\x1B[0K`
|
|
||||||
static String escClearLineFromCursorToEnd() => '\x1B[0K';
|
|
||||||
|
|
||||||
/// Clear line from cursor to start (Raw Sequence) `\x1B[1K`
|
|
||||||
static String escClearLineFromCursorToStart() => '\x1B[1K';
|
|
||||||
|
|
||||||
/// Clear entire line (Raw Sequence) `\x1B[2K`
|
|
||||||
static String escClearEntireLine() => '\x1B[2K';
|
|
||||||
|
|
||||||
/// Move cursor up **#** lines (Raw Sequence) `\x1B[#A`
|
|
||||||
static String escMoveUp(int n) => '\x1B[${n}A';
|
|
||||||
|
|
||||||
/// Move cursor down **#** lines (Raw Sequence) `\x1B[#B`
|
|
||||||
static String escMoveDown(int n) => '\x1B[${n}B';
|
|
||||||
|
|
||||||
/// Move cursor right **#** columns (Raw Sequence) `\x1B[#C`
|
|
||||||
static String escMoveRight(int n) => '\x1B[${n}C';
|
|
||||||
|
|
||||||
/// Move cursor left **#** columns (Raw Sequence) `\x1B[#D`
|
|
||||||
static String escMoveLeft(int n) => '\x1B[${n}D';
|
|
||||||
|
|
||||||
/// Move cursor down **#** lines and place cursor at start (Raw Sequence) `\x1B[#E`
|
|
||||||
static String escMoveDownAtStart(int n) => '\x1B[${n}E';
|
|
||||||
|
|
||||||
/// Move cursor up **#** lines and place cursor at start (Raw Sequence) `\x1B[#F`
|
|
||||||
static String escMoveUpAtStart(int n) => '\x1B[${n}F';
|
|
||||||
|
|
||||||
/// Move cursor on x axis **#** columens (Raw Sequence) `\x1B[#G`
|
|
||||||
static String escMoveHorizontal(int n) => '\x1B[${n}G';
|
|
||||||
|
|
||||||
/// Move cursor on x,y axis (Raw Sequence) `\x1B[$line;${column}H`
|
|
||||||
static String escMoveCursor(int line, int column) => '\x1B[$line;${column}H';
|
|
||||||
|
|
||||||
/// Save cursor position (Raw Sequence) `\x1B7`
|
|
||||||
static String escSavePosition() => '\x1B7';
|
|
||||||
|
|
||||||
/// Restore cursor position (Raw Sequence) `\x1B8`
|
|
||||||
static String escRestorePosition() => '\x1B8';
|
|
||||||
|
|
||||||
/// Hide cursor (Raw Sequence) `\x1B[?25l`
|
|
||||||
static String escHideCursor() => '\x1B[?25l';
|
|
||||||
|
|
||||||
/// Unhide cursor (Raw Sequence) `\x1B[?25h`
|
|
||||||
static String escUnhideCursor() => '\x1B[?25h';
|
|
||||||
|
|
||||||
/// Clear screen `\x1B[J`
|
|
||||||
static void clearScreen() => write(escClearScreen());
|
|
||||||
|
|
||||||
/// Clear screen from cursor to end `\x1B[0J`
|
|
||||||
static void clearScreenFromCursorToEnd() =>
|
|
||||||
write(escClearScreenFromCursorToEnd());
|
|
||||||
|
|
||||||
/// Clear screen from cursor to start `\x1B[1J`
|
|
||||||
static void clearScreenFromCursorToStart() =>
|
|
||||||
write(escClearScreenFromCursorToStart());
|
|
||||||
|
|
||||||
/// Clear entire screen `\x1B[2J`
|
|
||||||
static void clearEntireScreen() => write(escClearEntireScreen());
|
|
||||||
|
|
||||||
/// Clear line `\x1B[K`
|
|
||||||
static void clearLine() => write(escClearLine());
|
|
||||||
|
|
||||||
/// Clear line from cursor to end `\x1B[0K`
|
|
||||||
static void clearLineFromCursorToEnd() =>
|
|
||||||
write(escClearLineFromCursorToEnd());
|
|
||||||
|
|
||||||
/// Clear line from cursor to start `\x1B[1K`
|
|
||||||
static void clearLineFromCursorToStart() =>
|
|
||||||
write(escClearLineFromCursorToStart());
|
|
||||||
|
|
||||||
/// Clear entire line `\x1B[2K`
|
|
||||||
static void clearEntireLine() => write(escClearEntireLine());
|
|
||||||
|
|
||||||
/// Move cursor up **#** lines `\x1B[#A`
|
|
||||||
static void moveUp(int n) => write(escMoveUp(n));
|
|
||||||
|
|
||||||
/// Move cursor down **#** lines `\x1B[#B`
|
|
||||||
static void moveDown(int n) => write(escMoveDown(n));
|
|
||||||
|
|
||||||
/// Move cursor right **#** columns `\x1B[#C`
|
|
||||||
static void moveRight(int n) => write(escMoveRight(n));
|
|
||||||
|
|
||||||
/// Move cursor left **#** columns `\x1B[#D`
|
|
||||||
static void moveLeft(int n) => write(escMoveLeft(n));
|
|
||||||
|
|
||||||
/// Move cursor down **#** lines and place cursor at start `\x1B[#E`
|
|
||||||
static void moveDownAtStart(int n) => write(escMoveDownAtStart(n));
|
|
||||||
|
|
||||||
/// Move cursor up **#** lines and place cursor at start `\x1B[#F`
|
|
||||||
static void moveUpAtStart(int n) => write(escMoveUpAtStart(n));
|
|
||||||
|
|
||||||
/// Move cursor on x axis **#** columens `\x1B[#G`
|
|
||||||
static void moveHorizontal(int n) => write(escMoveHorizontal(n));
|
|
||||||
|
|
||||||
/// Move cursor on x,y axis `\x1B[$line;${column}H`
|
|
||||||
static void moveCursor(int line, int column) =>
|
|
||||||
write(escMoveCursor(line, column));
|
|
||||||
|
|
||||||
/// Save cursor position `\x1B7`
|
|
||||||
static void savePosition() => write(escSavePosition());
|
|
||||||
|
|
||||||
/// Restore cursor position `\x1B8`
|
|
||||||
static void restorePosition() => write(escRestorePosition());
|
|
||||||
|
|
||||||
/// Hide cursor `\x1B[?25l`
|
|
||||||
static void hideCursor() => write(escHideCursor());
|
|
||||||
|
|
||||||
/// Unhide cursor `\x1B[?25h`
|
|
||||||
static void unhideCursor() => write(escUnhideCursor());
|
|
||||||
|
|
||||||
/// Write string in standard output
|
|
||||||
static void write(String string) {
|
|
||||||
stdout.write(string);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Write string on new line in standard output
|
|
||||||
static void writeln(String string) {
|
|
||||||
stdout.writeln(string);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,99 +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:async';
|
|
||||||
import 'dart:io';
|
|
||||||
|
|
||||||
import 'package:wyatt_cli_toolbox/src/sequences/sequences.dart';
|
|
||||||
|
|
||||||
/// The [frames] field holds each individual frame of an animation, whilst the
|
|
||||||
/// [interval] represents the sleep time between each frame.
|
|
||||||
class Indicator {
|
|
||||||
|
|
||||||
Indicator({
|
|
||||||
required this.name,
|
|
||||||
required this.interval,
|
|
||||||
required this.frames,
|
|
||||||
this.label,
|
|
||||||
});
|
|
||||||
|
|
||||||
factory Indicator.fromMap(Map<String, Map<String, Object>> map) {
|
|
||||||
final String name = map.keys.first;
|
|
||||||
return Indicator(
|
|
||||||
name: name,
|
|
||||||
// ignore: cast_nullable_to_non_nullable
|
|
||||||
interval: map[name]!['interval'] as int,
|
|
||||||
// ignore: cast_nullable_to_non_nullable
|
|
||||||
frames: List<String>.from(map[name]!['frames'] as List<String>),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
final String name;
|
|
||||||
final int interval;
|
|
||||||
final List<String> frames;
|
|
||||||
final String? label;
|
|
||||||
Timer? _timer;
|
|
||||||
|
|
||||||
|
|
||||||
Map<String, Map<String, Object>> toMap() {
|
|
||||||
return <String, Map<String, Object>>{
|
|
||||||
name: <String, Object>{
|
|
||||||
'interval': interval,
|
|
||||||
'frames': frames,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Animate the spinner.
|
|
||||||
void animate() {
|
|
||||||
stop();
|
|
||||||
int frame = 0;
|
|
||||||
_timer = Timer.periodic(Duration(milliseconds: interval), (Timer t) {
|
|
||||||
Sequences.clearEntireLine();
|
|
||||||
frame = (frame + 1) % frames.length;
|
|
||||||
if (label != null) {
|
|
||||||
stdout.write('${frames[frame]} $label');
|
|
||||||
} else {
|
|
||||||
stdout.write(frames[frame]);
|
|
||||||
}
|
|
||||||
Sequences.moveHorizontal(1);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Stop the spinner (but don't kill isolate)
|
|
||||||
void stop() {
|
|
||||||
Sequences.clearEntireLine();
|
|
||||||
_timer?.cancel();
|
|
||||||
}
|
|
||||||
|
|
||||||
Indicator copyWith({
|
|
||||||
String? name,
|
|
||||||
int? interval,
|
|
||||||
List<String>? frames,
|
|
||||||
String? label,
|
|
||||||
}) {
|
|
||||||
return Indicator(
|
|
||||||
name: name ?? this.name,
|
|
||||||
interval: interval ?? this.interval,
|
|
||||||
frames: frames ?? this.frames,
|
|
||||||
label: label ?? this.label,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
String toString() =>
|
|
||||||
'Indicator(name: $name, interval: $interval, frames: $frames)';
|
|
||||||
}
|
|
||||||
@@ -1,66 +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:async';
|
|
||||||
import 'dart:isolate';
|
|
||||||
|
|
||||||
import 'package:wyatt_cli_toolbox/src/sequences/sequences.dart';
|
|
||||||
import 'package:wyatt_cli_toolbox/src/spinners/indicator.dart';
|
|
||||||
import 'package:wyatt_cli_toolbox/src/spinners/spinner_type.dart';
|
|
||||||
|
|
||||||
|
|
||||||
class Spinner {
|
|
||||||
/// Active isolate object. Is created when [start] is called.
|
|
||||||
static Isolate? _spinnerIsolate;
|
|
||||||
|
|
||||||
/// Run the animation of active [_spinnerIsolate].
|
|
||||||
static Future<void> _animate(Indicator indicator) async {
|
|
||||||
indicator.animate();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Starts an animation on a new line.
|
|
||||||
static Future<Isolate> start(SpinnerType spinner, {String? text}) async {
|
|
||||||
return custom(spinner.indicator.copyWith(label: text));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Starts a custom animation on a new line.
|
|
||||||
static Future<Isolate> custom(Indicator indicator) async {
|
|
||||||
Sequences.hideCursor();
|
|
||||||
return _spinnerIsolate ??
|
|
||||||
(_spinnerIsolate = await Isolate.spawn(
|
|
||||||
_animate,
|
|
||||||
indicator,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Stops current spinner animation by killing the isolate instance,
|
|
||||||
/// and clears current line.
|
|
||||||
static void stop() {
|
|
||||||
if (_spinnerIsolate != null) {
|
|
||||||
_spinnerIsolate!.kill(priority: Isolate.immediate);
|
|
||||||
}
|
|
||||||
_spinnerIsolate = null;
|
|
||||||
Sequences.clearEntireLine();
|
|
||||||
Sequences.moveHorizontal(1);
|
|
||||||
Sequences.unhideCursor();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Stop and restart a new indicator on same line.
|
|
||||||
static void update(Indicator indicator) {
|
|
||||||
stop();
|
|
||||||
custom(indicator);
|
|
||||||
}
|
|
||||||
}
|
|
||||||