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.
|
||||
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
|
||||
|
||||
### Changes
|
||||
|
||||
@@ -171,10 +171,16 @@ Note that your issue will be close after merging on master.
|
||||
Before closing the issue, please check tests and update coverage. You might run :
|
||||
|
||||
```shell
|
||||
melos run test
|
||||
melos run gen_coverage
|
||||
melos run test:all # this will run all tests in this project
|
||||
melos run gen-coverage # this will generate coverage report
|
||||
melos run gen-class-models # this will generate plantuml class diagrams
|
||||
melos run quality-check # this will run all targets generally expected in CI
|
||||
melos run publish:validate # this will run a validation before publish packages
|
||||
melos run publish # this will publish packages
|
||||
```
|
||||
|
||||
> Note that only modified package will be verified and published.
|
||||
|
||||
#### Merge your work
|
||||
|
||||
After closing your issue, some work may have been done on master in the meantime. To keep a clean git history, please rebase before opening a change request.
|
||||
|
||||
@@ -21,8 +21,7 @@ scripts:
|
||||
|
||||
analyze:
|
||||
run: |
|
||||
melos exec -c 10 -- \
|
||||
flutter analyze --fatal-infos
|
||||
melos exec -c 1 -- flutter analyze --fatal-infos
|
||||
description: Run `flutter analyze` for all packages.
|
||||
|
||||
format:
|
||||
@@ -38,18 +37,38 @@ scripts:
|
||||
description: Clean things very deeply with `git clean`.
|
||||
|
||||
test:selective_unit_test:
|
||||
run: melos exec --dir-exists="test" -- flutter test --no-pub --coverage
|
||||
run: melos exec -- flutter test --no-pub --coverage
|
||||
description: Run Flutter tests for a specific package in this project.
|
||||
select-package:
|
||||
flutter: true
|
||||
dir-exists:
|
||||
- test
|
||||
ignore:
|
||||
- '*example*'
|
||||
|
||||
test:
|
||||
test:all:
|
||||
run: melos run test:selective_unit_test --no-select
|
||||
description: Run all Flutter tests in this project.
|
||||
|
||||
gen-coverage: melos exec -- sh "\$MELOS_ROOT_PATH/combine_coverage.sh" && genhtml coverage/lcov.info -o coverage/html
|
||||
|
||||
gen-class-models: melos exec --scope="*wyatt_*" -- dart pub global run dcdg -o models/class-models.puml
|
||||
gen-class-models:
|
||||
run: melos exec -- dart pub global run dcdg -o models/class-models.puml
|
||||
select-package:
|
||||
ignore:
|
||||
- '*example*'
|
||||
|
||||
quality-check:
|
||||
run: |
|
||||
melos clean && \
|
||||
melos bootstrap && \
|
||||
melos run test:all
|
||||
description: Run all targets generally expected in CI for a full local quality check.
|
||||
|
||||
publish:validate:
|
||||
run: melos publish --diff="origin/$DRONE_COMMIT_BRANCH...HEAD" --yes
|
||||
|
||||
# publish:
|
||||
# run: melos publish --diff="origin/$DRONE_COMMIT_BRANCH...HEAD" --no-dry-run --yes
|
||||
|
||||
# Additional cleanup lifecycle script, executed when `melos clean` is run.
|
||||
postclean: >
|
||||
|
||||
@@ -1,3 +1,12 @@
|
||||
## 2.3.0
|
||||
|
||||
- **REFACTOR**: follow melos versioning.
|
||||
- **FIX**: change file include to keep coherence.
|
||||
- **FEAT**: exclude generated code, and add dart>2.16 rules.
|
||||
- **FEAT**: add overwrite protection.
|
||||
- **FEAT**: add 2.2.2 files for archive.
|
||||
- **FEAT**: add utils script to easely bump version.
|
||||
|
||||
## 2.2.2
|
||||
|
||||
- **DOCS**: add publish_to self hosted pub server.
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||

|
||||
|
||||
This package provides lint rules for Dart and Flutter which are used at [Wyatt](https://wyattapp.io) and [Wyatt Studio](https://wyatt-studio.fr). For more information, see the complete list of options in **lib/analysis_options.2.0.0.yaml**.
|
||||
This package provides lint rules for Dart and Flutter which are used at [Wyatt](https://wyattapp.io) and [Wyatt Studio](https://wyatt-studio.fr). For more information, see the complete list of options in **lib/analysis_options.2.3.0.yaml**.
|
||||
|
||||
**Note**: This package was heavily inspired by [pedantic](https://github.com/dart-lang/pedantic), [Very Good Analysis](https://github.com/VeryGoodOpenSource/very_good_analysis) and the official [flutter_lints](https://pub.dev/packages/flutter_lints).
|
||||
|
||||
@@ -29,12 +29,9 @@ This package provides lint rules for Dart and Flutter which are used at [Wyatt](
|
||||
To use the lints, add a dependency in your `pubspec.yaml`:
|
||||
|
||||
```yaml
|
||||
dev_dependencies:
|
||||
wyatt_analysis:
|
||||
git:
|
||||
url: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages
|
||||
ref: wyatt_analysis-v2.0.0
|
||||
path: packages/wyatt_analysis
|
||||
wyatt_analysis:
|
||||
hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub/
|
||||
version: 2.3.0
|
||||
```
|
||||
|
||||
Then, add an include in `analysis_options.yaml`:
|
||||
@@ -52,13 +49,13 @@ include: package:wyatt_analysis/analysis_options.flutter.yaml
|
||||
If you wish to restrict the lint version, specify a version of `analysis_options.yaml` instead:
|
||||
|
||||
```yaml
|
||||
include: package:wyatt_analysis/analysis_options.flutter.2.0.0.yaml
|
||||
include: package:wyatt_analysis/analysis_options.flutter.2.3.0.yaml
|
||||
```
|
||||
|
||||
If you just want **Dart** version:
|
||||
|
||||
```yaml
|
||||
include: package:wyatt_analysis/analysis_options.2.0.0.yaml
|
||||
include: package:wyatt_analysis/analysis_options.2.3.0.yaml
|
||||
```
|
||||
|
||||
## Suppressing Lints
|
||||
|
||||
@@ -0,0 +1,206 @@
|
||||
# Copyright (C) 2022 WYATT GROUP
|
||||
# Please see the AUTHORS file for details.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
analyzer:
|
||||
language:
|
||||
strict-casts: true
|
||||
strict-inference: true
|
||||
strict-raw-types: true
|
||||
|
||||
errors:
|
||||
todo: ignore
|
||||
close_sinks: ignore
|
||||
missing_required_param: error
|
||||
missing_return: error
|
||||
|
||||
exclude:
|
||||
- example/**
|
||||
- lib/l10n/**
|
||||
- lib/generated/**
|
||||
- lib/generated_plugin_registrant.dart
|
||||
- test/.test_coverage.dart
|
||||
|
||||
linter:
|
||||
rules:
|
||||
- always_declare_return_types
|
||||
- always_require_non_null_named_parameters
|
||||
- always_put_control_body_on_new_line
|
||||
- always_put_required_named_parameters_first
|
||||
- always_use_package_imports
|
||||
- annotate_overrides
|
||||
- avoid_bool_literals_in_conditional_expressions
|
||||
- avoid_catching_errors
|
||||
- avoid_double_and_int_checks
|
||||
- avoid_dynamic_calls
|
||||
- avoid_empty_else
|
||||
- avoid_equals_and_hash_code_on_mutable_classes
|
||||
- avoid_escaping_inner_quotes
|
||||
- avoid_field_initializers_in_const_classes
|
||||
- avoid_function_literals_in_foreach_calls
|
||||
- avoid_init_to_null
|
||||
- avoid_js_rounded_ints
|
||||
- avoid_null_checks_in_equality_operators
|
||||
- avoid_positional_boolean_parameters
|
||||
- avoid_private_typedef_functions
|
||||
- avoid_redundant_argument_values
|
||||
- avoid_relative_lib_imports
|
||||
- avoid_renaming_method_parameters
|
||||
- avoid_return_types_on_setters
|
||||
- avoid_returning_null
|
||||
- avoid_returning_null_for_future
|
||||
- avoid_returning_null_for_void
|
||||
- avoid_returning_this
|
||||
- avoid_setters_without_getters
|
||||
- avoid_shadowing_type_parameters
|
||||
- avoid_single_cascade_in_expression_statements
|
||||
- avoid_slow_async_io
|
||||
- avoid_type_to_string
|
||||
- avoid_types_as_parameter_names
|
||||
- avoid_types_on_closure_parameters
|
||||
- avoid_unused_constructor_parameters
|
||||
- avoid_void_async
|
||||
- await_only_futures
|
||||
- camel_case_extensions
|
||||
- camel_case_types
|
||||
- cancel_subscriptions
|
||||
- cascade_invocations
|
||||
- cast_nullable_to_non_nullable
|
||||
- comment_references
|
||||
- conditional_uri_does_not_exist
|
||||
- constant_identifier_names
|
||||
- control_flow_in_finally
|
||||
- curly_braces_in_flow_control_structures
|
||||
- depend_on_referenced_packages
|
||||
- deprecated_consistency
|
||||
- directives_ordering
|
||||
- empty_catches
|
||||
- empty_constructor_bodies
|
||||
- empty_statements
|
||||
- eol_at_end_of_file
|
||||
- exhaustive_cases
|
||||
- file_names
|
||||
- flutter_style_todos
|
||||
- hash_and_equals
|
||||
- implementation_imports
|
||||
- iterable_contains_unrelated_type
|
||||
- join_return_with_assignment
|
||||
- leading_newlines_in_multiline_strings
|
||||
- library_names
|
||||
- library_prefixes
|
||||
- library_private_types_in_public_api
|
||||
- lines_longer_than_80_chars
|
||||
- list_remove_unrelated_type
|
||||
- literal_only_boolean_expressions
|
||||
- missing_whitespace_between_adjacent_strings
|
||||
- no_adjacent_strings_in_list
|
||||
- no_default_cases
|
||||
- no_duplicate_case_values
|
||||
- no_leading_underscores_for_local_identifiers
|
||||
- no_runtimeType_toString
|
||||
- non_constant_identifier_names
|
||||
- noop_primitive_operations
|
||||
- null_check_on_nullable_type_parameter
|
||||
- null_closures
|
||||
- one_member_abstracts
|
||||
- only_throw_errors
|
||||
- overridden_fields
|
||||
- package_api_docs
|
||||
- package_names
|
||||
- package_prefixed_library_names
|
||||
- parameter_assignments
|
||||
- prefer_adjacent_string_concatenation
|
||||
- prefer_asserts_in_initializer_lists
|
||||
- prefer_asserts_with_message
|
||||
- prefer_collection_literals
|
||||
- prefer_conditional_assignment
|
||||
- prefer_const_constructors
|
||||
- prefer_const_constructors_in_immutables
|
||||
- prefer_const_declarations
|
||||
- prefer_const_literals_to_create_immutables
|
||||
- prefer_constructors_over_static_methods
|
||||
- prefer_contains
|
||||
- prefer_equal_for_default_values
|
||||
- prefer_expression_function_bodies
|
||||
- prefer_final_fields
|
||||
- prefer_final_in_for_each
|
||||
- prefer_final_locals
|
||||
- prefer_for_elements_to_map_fromIterable
|
||||
- prefer_function_declarations_over_variables
|
||||
- prefer_generic_function_type_aliases
|
||||
- prefer_if_elements_to_conditional_expressions
|
||||
- prefer_if_null_operators
|
||||
- prefer_initializing_formals
|
||||
- prefer_inlined_adds
|
||||
- prefer_int_literals
|
||||
- prefer_interpolation_to_compose_strings
|
||||
- prefer_is_empty
|
||||
- prefer_is_not_empty
|
||||
- prefer_is_not_operator
|
||||
- prefer_iterable_whereType
|
||||
- prefer_mixin
|
||||
- prefer_null_aware_operators
|
||||
- prefer_null_aware_method_calls
|
||||
- prefer_single_quotes
|
||||
- prefer_spread_collections
|
||||
- prefer_typing_uninitialized_variables
|
||||
- prefer_void_to_null
|
||||
- provide_deprecation_message
|
||||
- recursive_getters
|
||||
- require_trailing_commas
|
||||
- slash_for_doc_comments
|
||||
- sort_unnamed_constructors_first
|
||||
- test_types_in_equals
|
||||
- throw_in_finally
|
||||
- tighten_type_of_initializing_formals
|
||||
- type_annotate_public_apis
|
||||
- type_init_formals
|
||||
- unawaited_futures
|
||||
- unnecessary_await_in_return
|
||||
- unnecessary_brace_in_string_interps
|
||||
- unnecessary_const
|
||||
- unnecessary_constructor_name
|
||||
- unnecessary_getters_setters
|
||||
- unnecessary_lambdas
|
||||
- unnecessary_late
|
||||
- unnecessary_new
|
||||
- unnecessary_null_aware_assignments
|
||||
- unnecessary_null_checks
|
||||
- unnecessary_null_in_if_null_operators
|
||||
- unnecessary_nullable_for_final_variable_declarations
|
||||
- unnecessary_overrides
|
||||
- unnecessary_parenthesis
|
||||
- unnecessary_raw_strings
|
||||
- unnecessary_statements
|
||||
- unnecessary_string_escapes
|
||||
- unnecessary_string_interpolations
|
||||
- unnecessary_this
|
||||
- unrelated_type_equality_checks
|
||||
- unsafe_html
|
||||
- use_enums
|
||||
- use_function_type_syntax_for_parameters
|
||||
- use_if_null_to_convert_nulls_to_bools
|
||||
- use_is_even_rather_than_modulo
|
||||
- use_late_for_private_fields_and_variables
|
||||
- use_named_constants
|
||||
- use_raw_strings
|
||||
- use_rethrow_when_possible
|
||||
- use_setters_to_change_properties
|
||||
- use_string_buffers
|
||||
- use_super_parameters
|
||||
- use_test_throws_matchers
|
||||
- use_to_and_as_if_applicable
|
||||
- valid_regexps
|
||||
- void_checks
|
||||
@@ -0,0 +1,213 @@
|
||||
# Copyright (C) 2022 WYATT GROUP
|
||||
# Please see the AUTHORS file for details.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
analyzer:
|
||||
language:
|
||||
strict-casts: true
|
||||
strict-inference: true
|
||||
strict-raw-types: true
|
||||
|
||||
errors:
|
||||
todo: info
|
||||
close_sinks: ignore
|
||||
missing_required_param: error
|
||||
missing_return: error
|
||||
|
||||
exclude:
|
||||
- lib/l10n/**
|
||||
- lib/generated/**
|
||||
- lib/gen/**
|
||||
- lib/generated_plugin_registrant.dart
|
||||
- test/.test_coverage.dart
|
||||
- '**/*.g.dart'
|
||||
- '**/*.freezed.dart'
|
||||
|
||||
linter:
|
||||
rules:
|
||||
- always_declare_return_types
|
||||
- always_put_control_body_on_new_line
|
||||
- always_put_required_named_parameters_first
|
||||
- always_require_non_null_named_parameters
|
||||
- always_use_package_imports
|
||||
- annotate_overrides
|
||||
- avoid_bool_literals_in_conditional_expressions
|
||||
- avoid_catching_errors
|
||||
- avoid_double_and_int_checks
|
||||
- avoid_dynamic_calls
|
||||
- avoid_empty_else
|
||||
- avoid_equals_and_hash_code_on_mutable_classes
|
||||
- avoid_escaping_inner_quotes
|
||||
- avoid_field_initializers_in_const_classes
|
||||
- avoid_final_parameters
|
||||
- avoid_function_literals_in_foreach_calls
|
||||
- avoid_init_to_null
|
||||
- avoid_js_rounded_ints
|
||||
- avoid_multiple_declarations_per_line
|
||||
- avoid_null_checks_in_equality_operators
|
||||
- avoid_positional_boolean_parameters
|
||||
- avoid_private_typedef_functions
|
||||
- avoid_redundant_argument_values
|
||||
- avoid_relative_lib_imports
|
||||
- avoid_renaming_method_parameters
|
||||
- avoid_return_types_on_setters
|
||||
- avoid_returning_null
|
||||
- avoid_returning_null_for_future
|
||||
- avoid_returning_null_for_void
|
||||
- avoid_returning_this
|
||||
- avoid_setters_without_getters
|
||||
- avoid_shadowing_type_parameters
|
||||
- avoid_single_cascade_in_expression_statements
|
||||
- avoid_slow_async_io
|
||||
- avoid_type_to_string
|
||||
- avoid_types_as_parameter_names
|
||||
- avoid_types_on_closure_parameters
|
||||
- avoid_unused_constructor_parameters
|
||||
- avoid_void_async
|
||||
- await_only_futures
|
||||
- camel_case_extensions
|
||||
- camel_case_types
|
||||
- cancel_subscriptions
|
||||
- cascade_invocations
|
||||
- cast_nullable_to_non_nullable
|
||||
- comment_references
|
||||
- conditional_uri_does_not_exist
|
||||
- constant_identifier_names
|
||||
- control_flow_in_finally
|
||||
- curly_braces_in_flow_control_structures
|
||||
- depend_on_referenced_packages
|
||||
- deprecated_consistency
|
||||
- directives_ordering
|
||||
- empty_catches
|
||||
- empty_constructor_bodies
|
||||
- empty_statements
|
||||
- eol_at_end_of_file
|
||||
- exhaustive_cases
|
||||
- file_names
|
||||
- flutter_style_todos
|
||||
- hash_and_equals
|
||||
- implementation_imports
|
||||
- iterable_contains_unrelated_type
|
||||
- join_return_with_assignment
|
||||
- leading_newlines_in_multiline_strings
|
||||
- library_names
|
||||
- library_prefixes
|
||||
- library_private_types_in_public_api
|
||||
- lines_longer_than_80_chars
|
||||
- list_remove_unrelated_type
|
||||
- literal_only_boolean_expressions
|
||||
- missing_whitespace_between_adjacent_strings
|
||||
- no_adjacent_strings_in_list
|
||||
- no_default_cases
|
||||
- no_duplicate_case_values
|
||||
- no_leading_underscores_for_library_prefixes
|
||||
- no_leading_underscores_for_local_identifiers
|
||||
- no_runtimeType_toString
|
||||
- non_constant_identifier_names
|
||||
- noop_primitive_operations
|
||||
- null_check_on_nullable_type_parameter
|
||||
- null_closures
|
||||
- one_member_abstracts
|
||||
- only_throw_errors
|
||||
- overridden_fields
|
||||
- package_api_docs
|
||||
- package_names
|
||||
- package_prefixed_library_names
|
||||
- parameter_assignments
|
||||
- prefer_adjacent_string_concatenation
|
||||
- prefer_asserts_in_initializer_lists
|
||||
- prefer_asserts_with_message
|
||||
- prefer_collection_literals
|
||||
- prefer_conditional_assignment
|
||||
- prefer_const_constructors
|
||||
- prefer_const_constructors_in_immutables
|
||||
- prefer_const_declarations
|
||||
- prefer_const_literals_to_create_immutables
|
||||
- prefer_constructors_over_static_methods
|
||||
- prefer_contains
|
||||
- prefer_equal_for_default_values
|
||||
- prefer_expression_function_bodies
|
||||
- prefer_final_fields
|
||||
- prefer_final_in_for_each
|
||||
- prefer_final_locals
|
||||
- prefer_for_elements_to_map_fromIterable
|
||||
- prefer_function_declarations_over_variables
|
||||
- prefer_generic_function_type_aliases
|
||||
- prefer_if_elements_to_conditional_expressions
|
||||
- prefer_if_null_operators
|
||||
- prefer_initializing_formals
|
||||
- prefer_inlined_adds
|
||||
- prefer_int_literals
|
||||
- prefer_interpolation_to_compose_strings
|
||||
- prefer_is_empty
|
||||
- prefer_is_not_empty
|
||||
- prefer_is_not_operator
|
||||
- prefer_iterable_whereType
|
||||
- prefer_mixin
|
||||
- prefer_null_aware_method_calls
|
||||
- prefer_null_aware_operators
|
||||
- prefer_single_quotes
|
||||
- prefer_spread_collections
|
||||
- prefer_typing_uninitialized_variables
|
||||
- prefer_void_to_null
|
||||
- provide_deprecation_message
|
||||
- recursive_getters
|
||||
- require_trailing_commas
|
||||
- slash_for_doc_comments
|
||||
- sort_constructors_first
|
||||
- sort_unnamed_constructors_first
|
||||
- test_types_in_equals
|
||||
- throw_in_finally
|
||||
- tighten_type_of_initializing_formals
|
||||
- type_annotate_public_apis
|
||||
- type_init_formals
|
||||
- unawaited_futures
|
||||
- unnecessary_await_in_return
|
||||
- unnecessary_brace_in_string_interps
|
||||
- unnecessary_const
|
||||
- unnecessary_constructor_name
|
||||
- unnecessary_getters_setters
|
||||
- unnecessary_lambdas
|
||||
- unnecessary_late
|
||||
- unnecessary_new
|
||||
- unnecessary_null_aware_assignments
|
||||
- unnecessary_null_checks
|
||||
- unnecessary_null_in_if_null_operators
|
||||
- unnecessary_nullable_for_final_variable_declarations
|
||||
- unnecessary_overrides
|
||||
- unnecessary_parenthesis
|
||||
- unnecessary_raw_strings
|
||||
- unnecessary_statements
|
||||
- unnecessary_string_escapes
|
||||
- unnecessary_string_interpolations
|
||||
- unnecessary_this
|
||||
- unnecessary_to_list_in_spreads
|
||||
- unrelated_type_equality_checks
|
||||
- unsafe_html
|
||||
- use_enums
|
||||
- use_function_type_syntax_for_parameters
|
||||
- use_if_null_to_convert_nulls_to_bools
|
||||
- use_is_even_rather_than_modulo
|
||||
- use_late_for_private_fields_and_variables
|
||||
- use_named_constants
|
||||
- use_raw_strings
|
||||
- use_rethrow_when_possible
|
||||
- use_setters_to_change_properties
|
||||
- use_string_buffers
|
||||
- use_super_parameters
|
||||
- use_test_throws_matchers
|
||||
- use_to_and_as_if_applicable
|
||||
- valid_regexps
|
||||
- void_checks
|
||||
@@ -14,7 +14,7 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
include: package:wyatt_analysis/analysis_options.2.1.1.yaml
|
||||
include: package:wyatt_analysis/analysis_options.2.2.0.yaml
|
||||
|
||||
linter:
|
||||
rules:
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
# Copyright (C) 2022 WYATT GROUP
|
||||
# Please see the AUTHORS file for details.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
include: package:wyatt_analysis/analysis_options.2.2.2.yaml
|
||||
|
||||
linter:
|
||||
rules:
|
||||
- avoid_print
|
||||
- avoid_unnecessary_containers
|
||||
- avoid_web_libraries_in_flutter
|
||||
- no_logic_in_create_state
|
||||
- sized_box_for_whitespace
|
||||
- sized_box_shrink_expand
|
||||
- sort_child_properties_last
|
||||
- use_build_context_synchronously
|
||||
- use_colored_box
|
||||
- use_decorated_box
|
||||
- use_full_hex_values_for_flutter_colors
|
||||
- use_key_in_widget_constructors
|
||||
@@ -0,0 +1,32 @@
|
||||
# Copyright (C) 2022 WYATT GROUP
|
||||
# Please see the AUTHORS file for details.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
include: package:wyatt_analysis/analysis_options.2.3.0.yaml
|
||||
|
||||
linter:
|
||||
rules:
|
||||
- avoid_print
|
||||
- avoid_unnecessary_containers
|
||||
- avoid_web_libraries_in_flutter
|
||||
- no_logic_in_create_state
|
||||
- sized_box_for_whitespace
|
||||
- sized_box_shrink_expand
|
||||
- sort_child_properties_last
|
||||
- use_build_context_synchronously
|
||||
- use_colored_box
|
||||
- use_decorated_box
|
||||
- use_full_hex_values_for_flutter_colors
|
||||
- use_key_in_widget_constructors
|
||||
@@ -1,3 +1,4 @@
|
||||
|
||||
# Copyright (C) 2022 WYATT GROUP
|
||||
# Please see the AUTHORS file for details.
|
||||
#
|
||||
@@ -14,4 +15,5 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
include: package:wyatt_analysis/analysis_options.flutter.2.2.1.yaml
|
||||
include: package:wyatt_analysis/analysis_options.flutter.2.3.0.yaml
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
|
||||
# Copyright (C) 2022 WYATT GROUP
|
||||
# Please see the AUTHORS file for details.
|
||||
#
|
||||
@@ -14,4 +15,5 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
include: package:wyatt_analysis/analysis_options.2.2.1.yaml
|
||||
include: package:wyatt_analysis/analysis_options.2.3.0.yaml
|
||||
|
||||
|
||||
@@ -15,8 +15,7 @@
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
/// Wyatt analyzer settings and best practices
|
||||
/// used internally at [Wyatt](https://wyattapp.io)
|
||||
/// and [Wyatt Studio](https://wyatt-studio.fr).
|
||||
/// used internally at [Wyatt Studio](https://wyatt-studio.fr).
|
||||
library wyatt_analysis;
|
||||
|
||||
const String wyattAnalysisVersion = '2.2.1';
|
||||
const String wyattAnalysisVersion = '2.3.0';
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
# Copyright (C) 2022 WYATT GROUP
|
||||
# Please see the AUTHORS file for details.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
usage="
|
||||
usage:
|
||||
$(basename "$0") <previous_version> <new_version> -- create new analyzer files.
|
||||
|
||||
where:
|
||||
previous_version: last version, for example \`2.3.0\`
|
||||
new_version: new version, for example \`2.4.0\`"
|
||||
|
||||
old=$1
|
||||
new=$2
|
||||
|
||||
if [ -z "$old" ]; then
|
||||
echo "previous_version cannot be null"
|
||||
echo "${usage}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$new" ]; then
|
||||
echo "new_version cannot be null"
|
||||
echo "${usage}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
SCRIPT_PATH="${BASH_SOURCE:-$0}"
|
||||
ABS_SCRIPT_PATH="$(realpath "${SCRIPT_PATH}")"
|
||||
ABS_DIRECTORY="$(dirname "${ABS_SCRIPT_PATH}")"
|
||||
|
||||
LIB="${ABS_DIRECTORY}/lib/wyatt_analysis.dart"
|
||||
OPTIONS="${ABS_DIRECTORY}/lib/analysis_options.yaml"
|
||||
OLD_OPTIONS="${ABS_DIRECTORY}/lib/analysis_options.${old}.yaml"
|
||||
NEW_OPTIONS="${ABS_DIRECTORY}/lib/analysis_options.${new}.yaml"
|
||||
|
||||
OPTIONS_FLUTTER="${ABS_DIRECTORY}/lib/analysis_options.flutter.yaml"
|
||||
OLD_OPTIONS_FLUTTER="${ABS_DIRECTORY}/lib/analysis_options.flutter.${old}.yaml"
|
||||
NEW_OPTIONS_FLUTTER="${ABS_DIRECTORY}/lib/analysis_options.flutter.${new}.yaml"
|
||||
|
||||
if [ ! -e "$OLD_OPTIONS" ]; then
|
||||
echo "analysis_options.${old}.yaml doesn't exists"
|
||||
echo "${usage}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -e "$OLD_OPTIONS_FLUTTER" ]; then
|
||||
echo "analysis_options.flutter.${old}.yaml doesn't exists"
|
||||
echo "${usage}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -e "$NEW_OPTIONS" ]; then
|
||||
echo "analysis_options.${new}.yaml already exists"
|
||||
echo "${usage}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -e "$NEW_OPTIONS_FLUTTER" ]; then
|
||||
echo "analysis_options.flutter.${old}.yaml already exists"
|
||||
echo "${usage}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Copy previous version files
|
||||
cp "${OLD_OPTIONS}" "${NEW_OPTIONS}"
|
||||
cp "${OLD_OPTIONS_FLUTTER}" "${NEW_OPTIONS_FLUTTER}"
|
||||
|
||||
# Search and replace old version string occurences in new files
|
||||
sed -e "s/${old}/${new}/g" "${NEW_OPTIONS_FLUTTER}" > tempfile.tmp
|
||||
mv -f tempfile.tmp "${NEW_OPTIONS_FLUTTER}"
|
||||
|
||||
sed -e "s/${old}/${new}/g" "${LIB}" > tempfile.tmp
|
||||
mv -f tempfile.tmp "${LIB}"
|
||||
|
||||
sed -e "s/${old}/${new}/g" "README.md" > tempfile.tmp
|
||||
mv -f tempfile.tmp "README.md"
|
||||
|
||||
echo "
|
||||
# Copyright (C) 2022 WYATT GROUP
|
||||
# Please see the AUTHORS file for details.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
include: package:wyatt_analysis/analysis_options.${new}.yaml
|
||||
" > "${OPTIONS}"
|
||||
|
||||
echo "
|
||||
# Copyright (C) 2022 WYATT GROUP
|
||||
# Please see the AUTHORS file for details.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
include: package:wyatt_analysis/analysis_options.flutter.${new}.yaml
|
||||
" > "${OPTIONS_FLUTTER}"
|
||||
|
||||
exit 0
|
||||
@@ -1,7 +1,7 @@
|
||||
name: wyatt_analysis
|
||||
description: Lint rules for Dart and Flutter used internally at Wyatt and Wyatt Studio.
|
||||
description: Lint rules for Dart and Flutter used internally at Wyatt Studio.
|
||||
repository: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages/src/branch/master/packages/wyatt_analysis
|
||||
version: 2.2.2
|
||||
version: 2.3.0
|
||||
|
||||
publish_to: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ dev_dependencies:
|
||||
wyatt_analysis:
|
||||
git:
|
||||
url: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages
|
||||
ref: wyatt_analysis-v2.2.2
|
||||
ref: wyatt_analysis-v2.3.0
|
||||
path: packages/wyatt_analysis
|
||||
|
||||
# For information on the generic Dart part of this file, see the
|
||||
|
||||
@@ -24,4 +24,4 @@ dev_dependencies:
|
||||
|
||||
wyatt_analysis:
|
||||
hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub
|
||||
version: ^2.2.2
|
||||
version: ^2.3.0
|
||||
@@ -1,11 +1,18 @@
|
||||
// Author: Hugo Pointcheval
|
||||
// Email: git@pcl.ovh
|
||||
// -----
|
||||
// File: bootstrap.dart
|
||||
// Created Date: 19/08/2022 15:05:17
|
||||
// Last Modified: Fri Nov 11 2022
|
||||
// -----
|
||||
// Copyright (c) 2022
|
||||
// Copyright (C) 2022 WYATT GROUP
|
||||
// Please see the AUTHORS file for details.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
|
||||
@@ -1,12 +1,20 @@
|
||||
// Author: Hugo Pointcheval
|
||||
// Email: git@pcl.ovh
|
||||
// -----
|
||||
// File: form_field.dart
|
||||
// Created Date: 19/08/2022 11:52:33
|
||||
// Last Modified: 19/08/2022 16:35:39
|
||||
// -----
|
||||
// Copyright (c) 2022
|
||||
// Copyright (C) 2022 WYATT GROUP
|
||||
// Please see the AUTHORS file for details.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
abstract class AppFormField {
|
||||
static const oldPassword = 'oldPassword';
|
||||
static const confirmedPassword = 'confirmedPassword';
|
||||
}
|
||||
|
||||
@@ -14,6 +14,6 @@
|
||||
// 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';
|
||||
|
||||
bool get supportsAnsiColor => stdout.supportsAnsiEscapes;
|
||||
abstract class AppFormName {
|
||||
static const editProfile = 'editProfile';
|
||||
}
|
||||
@@ -1,12 +1,20 @@
|
||||
// Author: Hugo Pointcheval
|
||||
// Email: git@pcl.ovh
|
||||
// -----
|
||||
// File: router.dart
|
||||
// Created Date: 19/08/2022 11:52:22
|
||||
// Last Modified: 19/08/2022 16:39:07
|
||||
// -----
|
||||
// Copyright (c) 2022
|
||||
// Copyright (C) 2022 WYATT GROUP
|
||||
// Please see the AUTHORS file for details.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import 'package:example_router/presentation/features/edit_profile/edit_profile_page.dart';
|
||||
import 'package:example_router/presentation/features/home/home_page.dart';
|
||||
import 'package:example_router/presentation/features/sign_in/sign_in_page.dart';
|
||||
import 'package:example_router/presentation/features/sign_up/sign_up_page.dart';
|
||||
@@ -75,5 +83,14 @@ class AppRouter {
|
||||
const SubPage(),
|
||||
),
|
||||
),
|
||||
GoRoute(
|
||||
path: '/home/edit',
|
||||
name: EditProfilePage.pageName,
|
||||
pageBuilder: (context, state) => defaultTransition(
|
||||
context,
|
||||
state,
|
||||
const EditProfilePage(),
|
||||
),
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -1,11 +1,18 @@
|
||||
// Author: Hugo Pointcheval
|
||||
// Email: git@pcl.ovh
|
||||
// -----
|
||||
// File: app_bloc_observer.dart
|
||||
// Created Date: 19/08/2022 12:02:23
|
||||
// Last Modified: 19/08/2022 12:02:45
|
||||
// -----
|
||||
// Copyright (c) 2022
|
||||
// Copyright (C) 2022 WYATT GROUP
|
||||
// Please see the AUTHORS file for details.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
@@ -14,37 +14,19 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
part of prompt.framework;
|
||||
import 'package:example_router/core/constants/form_field.dart';
|
||||
import 'package:example_router/core/constants/form_name.dart';
|
||||
import 'package:example_router/core/utils/custom_password.dart';
|
||||
import 'package:wyatt_authentication_bloc/wyatt_authentication_bloc.dart';
|
||||
import 'package:wyatt_form_bloc/wyatt_form_bloc.dart';
|
||||
|
||||
abstract class State<W extends Widget<dynamic>> {
|
||||
W? _widget;
|
||||
W get widget => _widget!;
|
||||
|
||||
BuildContext? _context;
|
||||
BuildContext get context => _context!;
|
||||
|
||||
void build();
|
||||
|
||||
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();
|
||||
}
|
||||
abstract class AppForms {
|
||||
static WyattForm getEditProfileForm() => WyattFormImpl(
|
||||
[
|
||||
FormInput(AuthFormField.email, const Email.pure()),
|
||||
FormInput(AuthFormField.password, const CustomPassword.pure()),
|
||||
FormInput(AppFormField.oldPassword, const CustomPassword.pure()),
|
||||
],
|
||||
name: AppFormName.editProfile,
|
||||
);
|
||||
}
|
||||
@@ -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/presentation/features/app/app.dart';
|
||||
|
||||
|
||||
@@ -1,11 +1,18 @@
|
||||
// Author: Hugo Pointcheval
|
||||
// Email: git@pcl.ovh
|
||||
// -----
|
||||
// File: app.dart
|
||||
// Created Date: 19/08/2022 12:05:38
|
||||
// Last Modified: Sat Dec 03 2022
|
||||
// -----
|
||||
// Copyright (c) 2022
|
||||
// Copyright (C) 2022 WYATT GROUP
|
||||
// Please see the AUTHORS file for details.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:math';
|
||||
@@ -14,6 +21,7 @@ import 'package:example_router/core/constants/form_field.dart';
|
||||
import 'package:example_router/core/dependency_injection/get_it.dart';
|
||||
import 'package:example_router/core/routes/router.dart';
|
||||
import 'package:example_router/core/utils/custom_password.dart';
|
||||
import 'package:example_router/core/utils/forms.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
@@ -69,7 +77,7 @@ class App extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
AuthenticationState? previous;
|
||||
AuthenticationState<int>? previous;
|
||||
|
||||
final AuthenticationCubit<int> authenticationCubit =
|
||||
AuthenticationCubit(authenticationRepository: authenticationRepository);
|
||||
@@ -85,29 +93,18 @@ class App extends StatelessWidget {
|
||||
redirect: (context, state) {
|
||||
final authState = authenticationCubit.state;
|
||||
|
||||
if (authState != previous) {
|
||||
if (authState.status != previous?.status) {
|
||||
previous = authState;
|
||||
// Check if current user is logged in
|
||||
final loggedIn =
|
||||
authState.status == AuthenticationStatus.authenticated;
|
||||
|
||||
// Checking if current path is onboarding or not
|
||||
final isOnboarding = AppRouter.publicRoutes.contains(state.subloc);
|
||||
|
||||
if (!loggedIn) {
|
||||
if (authState.status == AuthenticationStatus.unauthenticated) {
|
||||
debugPrint('Not logged');
|
||||
if (isOnboarding) {
|
||||
return null;
|
||||
} else {
|
||||
if (!isOnboarding) {
|
||||
return '/';
|
||||
}
|
||||
} else {
|
||||
} else if (authState.status == AuthenticationStatus.authenticated) {
|
||||
debugPrint('Logged');
|
||||
if (isOnboarding) {
|
||||
return '/home';
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
return '/home';
|
||||
}
|
||||
}
|
||||
return null;
|
||||
@@ -116,9 +113,13 @@ class App extends StatelessWidget {
|
||||
|
||||
return MultiRepositoryProvider(
|
||||
providers: [
|
||||
RepositoryProvider<AuthenticationRepository>.value(
|
||||
RepositoryProvider<AuthenticationRepository<int>>.value(
|
||||
value: authenticationRepository,
|
||||
),
|
||||
RepositoryProvider<FormRepository>(
|
||||
create: (context) =>
|
||||
FormRepositoryImpl()..registerForm(AppForms.getEditProfileForm()),
|
||||
),
|
||||
],
|
||||
child: MultiBlocProvider(
|
||||
providers: [
|
||||
|
||||
@@ -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
|
||||
// Email: git@pcl.ovh
|
||||
// -----
|
||||
// File: home_page.dart
|
||||
// Created Date: 19/08/2022 14:38:24
|
||||
// Last Modified: Wed Nov 09 2022
|
||||
// -----
|
||||
// Copyright (c) 2022
|
||||
// Copyright (C) 2022 WYATT GROUP
|
||||
// Please see the AUTHORS file for details.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import 'package:example_router/presentation/features/edit_profile/edit_profile_page.dart';
|
||||
import 'package:example_router/presentation/features/sub/sub_page.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
@@ -25,7 +33,8 @@ class HomePage extends StatelessWidget {
|
||||
title: const Text('Home'),
|
||||
actions: [
|
||||
IconButton(
|
||||
onPressed: () => context.read<AuthenticationCubit<int>>().signOut(),
|
||||
onPressed: () =>
|
||||
context.read<AuthenticationCubit<int>>().signOut(),
|
||||
icon: const Icon(Icons.logout_rounded))
|
||||
],
|
||||
),
|
||||
@@ -35,8 +44,8 @@ class HomePage extends StatelessWidget {
|
||||
child: Column(
|
||||
children: [
|
||||
AuthenticationBuilder<int>(
|
||||
authenticated: (context, accountWrapper) =>
|
||||
Text('Logged as ${accountWrapper.account?.email} | GeneratedId is ${accountWrapper.data}'),
|
||||
authenticated: (context, accountWrapper) => Text(
|
||||
'Logged as ${accountWrapper.account?.email} | GeneratedId is ${accountWrapper.data}'),
|
||||
unauthenticated: (context) =>
|
||||
const Text('Not logged (unauthenticated)'),
|
||||
unknown: (context) => const Text('Not logged (unknown)'),
|
||||
@@ -45,8 +54,13 @@ class HomePage extends StatelessWidget {
|
||||
height: 8,
|
||||
),
|
||||
ElevatedButton(
|
||||
onPressed: () => context.pushNamed(SubPage.pageName),
|
||||
child: const Text('Go to sub page')),
|
||||
onPressed: () => context.pushNamed(SubPage.pageName),
|
||||
child: const Text('Go to sub page'),
|
||||
),
|
||||
ElevatedButton(
|
||||
onPressed: () => context.pushNamed(EditProfilePage.pageName),
|
||||
child: const Text('Go to edit profile page'),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
@@ -1,11 +1,18 @@
|
||||
// Author: Hugo Pointcheval
|
||||
// Email: git@pcl.ovh
|
||||
// -----
|
||||
// File: sign_in_page.dart
|
||||
// Created Date: 19/08/2022 12:41:42
|
||||
// Last Modified: 19/08/2022 15:26:36
|
||||
// -----
|
||||
// Copyright (c) 2022
|
||||
// Copyright (C) 2022 WYATT GROUP
|
||||
// Please see the AUTHORS file for details.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import 'package:example_router/presentation/features/sign_in/widgets/sign_in_form.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
@@ -1,11 +1,18 @@
|
||||
// Author: Hugo Pointcheval
|
||||
// Email: git@pcl.ovh
|
||||
// -----
|
||||
// File: sign_in_form.dart
|
||||
// Created Date: 19/08/2022 15:24:37
|
||||
// Last Modified: Sat Dec 03 2022
|
||||
// -----
|
||||
// Copyright (c) 2022
|
||||
// Copyright (C) 2022 WYATT GROUP
|
||||
// Please see the AUTHORS file for details.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import 'package:example_router/core/utils/custom_password.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
@@ -1,11 +1,18 @@
|
||||
// Author: Hugo Pointcheval
|
||||
// Email: git@pcl.ovh
|
||||
// -----
|
||||
// File: sign_up_page.dart
|
||||
// Created Date: 19/08/2022 12:41:27
|
||||
// Last Modified: 19/08/2022 14:58:51
|
||||
// -----
|
||||
// Copyright (c) 2022
|
||||
// Copyright (C) 2022 WYATT GROUP
|
||||
// Please see the AUTHORS file for details.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import 'package:example_router/presentation/features/sign_up/widgets/sign_up_form.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
@@ -1,11 +1,18 @@
|
||||
// Author: Hugo Pointcheval
|
||||
// Email: git@pcl.ovh
|
||||
// -----
|
||||
// File: sign_up_form.dart
|
||||
// Created Date: 19/08/2022 14:41:08
|
||||
// Last Modified: Sat Dec 03 2022
|
||||
// -----
|
||||
// Copyright (c) 2022
|
||||
// Copyright (C) 2022 WYATT GROUP
|
||||
// Please see the AUTHORS file for details.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import 'package:example_router/core/constants/form_field.dart';
|
||||
import 'package:example_router/core/utils/custom_password.dart';
|
||||
|
||||
@@ -1,11 +1,18 @@
|
||||
// Author: Hugo Pointcheval
|
||||
// Email: git@pcl.ovh
|
||||
// -----
|
||||
// File: sub_page.dart
|
||||
// Created Date: 19/08/2022 16:10:05
|
||||
// Last Modified: Wed Nov 09 2022
|
||||
// -----
|
||||
// Copyright (c) 2022
|
||||
// Copyright (C) 2022 WYATT GROUP
|
||||
// Please see the AUTHORS file for details.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
@@ -24,7 +31,10 @@ class SubPage extends StatelessWidget {
|
||||
actions: [
|
||||
IconButton(
|
||||
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(
|
||||
|
||||
@@ -1,11 +1,18 @@
|
||||
// Author: Hugo Pointcheval
|
||||
// Email: git@pcl.ovh
|
||||
// -----
|
||||
// File: welcome_page.dart
|
||||
// Created Date: 19/08/2022 12:33:21
|
||||
// Last Modified: Wed Nov 09 2022
|
||||
// -----
|
||||
// Copyright (c) 2022
|
||||
// Copyright (C) 2022 WYATT GROUP
|
||||
// Please see the AUTHORS file for details.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import 'package:example_router/presentation/features/sign_in/sign_in_page.dart';
|
||||
import 'package:example_router/presentation/features/sign_up/sign_up_page.dart';
|
||||
|
||||
@@ -256,3 +256,24 @@ abstract class GetIdTokenFailureInterface
|
||||
|
||||
GetIdTokenFailureInterface.fromCode(super.code) : super.fromCode();
|
||||
}
|
||||
|
||||
abstract class ReauthenticateFailureInterface
|
||||
extends AuthenticationFailureInterface {
|
||||
ReauthenticateFailureInterface(super.code, super.msg);
|
||||
|
||||
ReauthenticateFailureInterface.fromCode(super.code) : super.fromCode();
|
||||
}
|
||||
|
||||
abstract class UpdateEmailFailureInterface
|
||||
extends AuthenticationFailureInterface {
|
||||
UpdateEmailFailureInterface(super.code, super.msg);
|
||||
|
||||
UpdateEmailFailureInterface.fromCode(super.code) : super.fromCode();
|
||||
}
|
||||
|
||||
abstract class UpdatePasswordFailureInterface
|
||||
extends AuthenticationFailureInterface {
|
||||
UpdatePasswordFailureInterface(super.code, super.msg);
|
||||
|
||||
UpdatePasswordFailureInterface.fromCode(super.code) : super.fromCode();
|
||||
}
|
||||
|
||||
@@ -277,3 +277,75 @@ class GetIdTokenFailureFirebase extends GetIdTokenFailureInterface {
|
||||
|
||||
GetIdTokenFailureFirebase.fromCode(super.code) : super.fromCode();
|
||||
}
|
||||
|
||||
class ReauthenticateFailureFirebase extends ReauthenticateFailureInterface {
|
||||
ReauthenticateFailureFirebase([String? code, String? msg])
|
||||
: super(code ?? 'unknown', msg ?? 'An unknown error occurred.');
|
||||
ReauthenticateFailureFirebase.fromCode(String code) : super.fromCode(code) {
|
||||
switch (code) {
|
||||
case 'user-mismatch':
|
||||
msg = 'Given credential does not correspond to the user.';
|
||||
break;
|
||||
case 'user-not-found':
|
||||
msg = 'User is not found, please create an account.';
|
||||
break;
|
||||
case 'invalid-credential':
|
||||
msg = 'The credential received is malformed or has expired.';
|
||||
break;
|
||||
case 'invalid-email':
|
||||
msg = 'Email is not valid or badly formatted.';
|
||||
break;
|
||||
case 'wrong-password':
|
||||
msg = 'Incorrect password, please try again.';
|
||||
break;
|
||||
case 'invalid-verification-code':
|
||||
msg = 'The credential verification code received is invalid.';
|
||||
break;
|
||||
case 'invalid-verification-id':
|
||||
msg = 'The credential verification ID received is invalid.';
|
||||
break;
|
||||
default:
|
||||
this.code = 'unknown';
|
||||
msg = 'An unknown error occurred.';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class UpdateEmailFailureFirebase extends UpdateEmailFailureInterface {
|
||||
UpdateEmailFailureFirebase([String? code, String? msg])
|
||||
: super(code ?? 'unknown', msg ?? 'An unknown error occurred.');
|
||||
UpdateEmailFailureFirebase.fromCode(String code) : super.fromCode(code) {
|
||||
switch (code) {
|
||||
case 'invalid-email':
|
||||
msg = 'Email is not valid or badly formatted.';
|
||||
break;
|
||||
case 'email-already-in-use':
|
||||
msg = 'An account already exists for that email.';
|
||||
break;
|
||||
case 'requires-recent-login':
|
||||
msg = "User's last sign-in time does not meet the security threshold.";
|
||||
break;
|
||||
default:
|
||||
this.code = 'unknown';
|
||||
msg = 'An unknown error occurred.';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class UpdatePasswordFailureFirebase extends UpdatePasswordFailureInterface {
|
||||
UpdatePasswordFailureFirebase([String? code, String? msg])
|
||||
: super(code ?? 'unknown', msg ?? 'An unknown error occurred.');
|
||||
UpdatePasswordFailureFirebase.fromCode(String code) : super.fromCode(code) {
|
||||
switch (code) {
|
||||
case 'weak-password':
|
||||
msg = 'Please enter a stronger password.';
|
||||
break;
|
||||
case 'requires-recent-login':
|
||||
msg = "User's last sign-in time does not meet the security threshold.";
|
||||
break;
|
||||
default:
|
||||
this.code = 'unknown';
|
||||
msg = 'An unknown error occurred.';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import 'package:wyatt_type_utils/wyatt_type_utils.dart';
|
||||
class AuthenticationFirebaseDataSourceImpl
|
||||
extends AuthenticationRemoteDataSource {
|
||||
final FirebaseAuth _firebaseAuth;
|
||||
UserCredential? _latestCreds;
|
||||
|
||||
AuthenticationFirebaseDataSourceImpl({FirebaseAuth? firebaseAuth})
|
||||
: _firebaseAuth = firebaseAuth ?? FirebaseAuth.instance;
|
||||
@@ -51,6 +52,7 @@ class AuthenticationFirebaseDataSourceImpl
|
||||
email: email,
|
||||
password: password,
|
||||
);
|
||||
_latestCreds = userCredential;
|
||||
final user = userCredential.user;
|
||||
if (user.isNotNull) {
|
||||
return _mapper(user!);
|
||||
@@ -76,6 +78,7 @@ class AuthenticationFirebaseDataSourceImpl
|
||||
email: email,
|
||||
password: password,
|
||||
);
|
||||
_latestCreds = userCredential;
|
||||
final user = userCredential.user;
|
||||
if (user.isNotNull) {
|
||||
return _mapper(user!);
|
||||
@@ -92,6 +95,7 @@ class AuthenticationFirebaseDataSourceImpl
|
||||
@override
|
||||
Future<void> signOut() async {
|
||||
try {
|
||||
_latestCreds = null;
|
||||
await _firebaseAuth.signOut();
|
||||
} catch (_) {
|
||||
throw SignOutFailureFirebase();
|
||||
@@ -164,6 +168,7 @@ class AuthenticationFirebaseDataSourceImpl
|
||||
Future<Account> signInAnonymously() async {
|
||||
try {
|
||||
final userCredential = await _firebaseAuth.signInAnonymously();
|
||||
_latestCreds = userCredential;
|
||||
final user = userCredential.user;
|
||||
if (user.isNotNull) {
|
||||
return _mapper(user!);
|
||||
@@ -199,4 +204,60 @@ class AuthenticationFirebaseDataSourceImpl
|
||||
throw RefreshFailureFirebase();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Account> reauthenticateWithCredential() async {
|
||||
try {
|
||||
if (_latestCreds?.credential != null) {
|
||||
await _firebaseAuth.currentUser
|
||||
?.reauthenticateWithCredential(_latestCreds!.credential!);
|
||||
} else {
|
||||
throw Exception(); // Get caught just after.
|
||||
}
|
||||
final user = _firebaseAuth.currentUser;
|
||||
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 {
|
||||
Pair<Account, String>? _connectedMock;
|
||||
Pair<Account, String>? _registeredMock;
|
||||
DateTime _lastSignInTime = DateTime.now();
|
||||
final StreamController<Account?> _streamAccount = StreamController()
|
||||
..add(null);
|
||||
|
||||
@@ -118,6 +119,7 @@ class AuthenticationMockDataSourceImpl extends AuthenticationRemoteDataSource {
|
||||
);
|
||||
_streamAccount.add(mock);
|
||||
_connectedMock = _connectedMock?.copyWith(left: mock);
|
||||
_lastSignInTime = DateTime.now();
|
||||
return Future.value(mock);
|
||||
}
|
||||
|
||||
@@ -149,6 +151,7 @@ class AuthenticationMockDataSourceImpl extends AuthenticationRemoteDataSource {
|
||||
}
|
||||
_streamAccount.add(_registeredMock!.left);
|
||||
_connectedMock = _registeredMock!.copyWith();
|
||||
_lastSignInTime = DateTime.now();
|
||||
return _registeredMock!.left!;
|
||||
}
|
||||
throw SignInWithCredentialFailureFirebase();
|
||||
@@ -193,6 +196,8 @@ class AuthenticationMockDataSourceImpl extends AuthenticationRemoteDataSource {
|
||||
);
|
||||
_streamAccount.add(mock);
|
||||
_registeredMock = Pair(mock, password);
|
||||
_connectedMock = _registeredMock!.copyWith();
|
||||
_lastSignInTime = DateTime.now();
|
||||
return Future.value(mock);
|
||||
}
|
||||
|
||||
@@ -204,4 +209,45 @@ class AuthenticationMockDataSourceImpl extends AuthenticationRemoteDataSource {
|
||||
await _randomDelay();
|
||||
return true;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Account> reauthenticateWithCredential() async {
|
||||
await _randomDelay();
|
||||
if (_connectedMock.isNull) {
|
||||
throw ReauthenticateFailureFirebase();
|
||||
}
|
||||
await refresh();
|
||||
_lastSignInTime = DateTime.now();
|
||||
return Future.value(_connectedMock?.left);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Account> updateEmail({required String email}) {
|
||||
final before = DateTime.now().subtract(const Duration(seconds: 10));
|
||||
if (_lastSignInTime.isBefore(before)) {
|
||||
throw UpdateEmailFailureFirebase('requires-recent-login');
|
||||
}
|
||||
final refresh = DateTime.now();
|
||||
final mock = (_connectedMock?.left as AccountModel?)
|
||||
?.copyWith(lastSignInTime: refresh, email: email);
|
||||
_connectedMock = _connectedMock?.copyWith(left: mock);
|
||||
_registeredMock = _registeredMock?.copyWith(left: mock);
|
||||
_streamAccount.add(mock);
|
||||
return Future.value(_connectedMock?.left);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Account> updatePassword({required String password}) {
|
||||
final before = DateTime.now().subtract(const Duration(seconds: 10));
|
||||
if (_lastSignInTime.isBefore(before)) {
|
||||
throw UpdatePasswordFailureFirebase('requires-recent-login');
|
||||
}
|
||||
final refresh = DateTime.now();
|
||||
final mock = (_connectedMock?.left as AccountModel?)
|
||||
?.copyWith(lastSignInTime: refresh);
|
||||
_connectedMock = _connectedMock?.copyWith(left: mock, right: password);
|
||||
_registeredMock = _registeredMock?.copyWith(left: mock, right: password);
|
||||
_streamAccount.add(mock);
|
||||
return Future.value(_connectedMock?.left);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -314,4 +314,38 @@ class AuthenticationRepositoryImpl<T extends Object>
|
||||
},
|
||||
(error) => error,
|
||||
);
|
||||
|
||||
@override
|
||||
FutureOrResult<Account> reauthenticateWithCredential() =>
|
||||
Result.tryCatchAsync<Account, AppException, AppException>(
|
||||
() async {
|
||||
final account = await _authenticationRemoteDataSource
|
||||
.reauthenticateWithCredential();
|
||||
return account;
|
||||
},
|
||||
(error) => error,
|
||||
);
|
||||
|
||||
@override
|
||||
FutureOrResult<Account> updateEmail({required String email}) =>
|
||||
Result.tryCatchAsync<Account, AppException, AppException>(
|
||||
() async {
|
||||
final account =
|
||||
await _authenticationRemoteDataSource.updateEmail(email: email);
|
||||
return account;
|
||||
},
|
||||
(error) => error,
|
||||
);
|
||||
|
||||
@override
|
||||
FutureOrResult<Account> updatePassword({required String password}) =>
|
||||
Result.tryCatchAsync<Account, AppException, AppException>(
|
||||
() async {
|
||||
final account = await _authenticationRemoteDataSource.updatePassword(
|
||||
password: password,
|
||||
);
|
||||
return account;
|
||||
},
|
||||
(error) => error,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -48,4 +48,10 @@ abstract class AuthenticationRemoteDataSource extends BaseRemoteDataSource {
|
||||
Future<bool> verifyPasswordResetCode({required String code});
|
||||
|
||||
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,
|
||||
});
|
||||
|
||||
/// {@template update_email}
|
||||
/// Update or add [email].
|
||||
///
|
||||
/// Throws a UpdateEmailFailureInterface if
|
||||
/// an exception occurs.
|
||||
/// {@endtemplate}
|
||||
FutureOrResult<Account> updateEmail({
|
||||
required String email,
|
||||
});
|
||||
|
||||
/// {@template update_password}
|
||||
/// Update or add [password].
|
||||
///
|
||||
/// Throws a UpdatePasswordFailureInterface if
|
||||
/// an exception occurs.
|
||||
/// {@endtemplate}
|
||||
FutureOrResult<Account> updatePassword({
|
||||
required String password,
|
||||
});
|
||||
|
||||
/// {@template reauthenticate}
|
||||
/// Some security-sensitive actions—such as deleting an account,
|
||||
/// setting a primary email address, and changing a password—require that
|
||||
/// the user has recently signed in.
|
||||
///
|
||||
/// Throws a ReauthenticateFailureInterface if
|
||||
/// an exception occurs.
|
||||
/// {@endtemplate}
|
||||
FutureOrResult<Account> reauthenticateWithCredential();
|
||||
|
||||
/// {@template signout}
|
||||
/// Signs out the current user.
|
||||
/// It also clears the cache and the associated data.
|
||||
/// {@endtemplate}
|
||||
FutureOrResult<void> signOut();
|
||||
|
||||
/// {@template refresh}
|
||||
/// Refreshes the current user, if signed in.
|
||||
/// {@endtemplate}
|
||||
FutureOrResult<void> refresh();
|
||||
|
||||
/// {@template stream_account}
|
||||
|
||||
@@ -43,4 +43,4 @@ dev_dependencies:
|
||||
|
||||
wyatt_analysis:
|
||||
hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub/
|
||||
version: 2.2.2
|
||||
version: 2.3.0
|
||||
|
||||
@@ -22,4 +22,4 @@ dev_dependencies:
|
||||
|
||||
wyatt_analysis:
|
||||
hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub
|
||||
version: ^2.2.2
|
||||
version: ^2.3.0
|
||||
@@ -0,0 +1,133 @@
|
||||
# Miscellaneous
|
||||
*.class
|
||||
*.lock
|
||||
*.log
|
||||
*.pyc
|
||||
*.swp
|
||||
.DS_Store
|
||||
.atom/
|
||||
.buildlog/
|
||||
.history
|
||||
.svn/
|
||||
|
||||
# IntelliJ related
|
||||
*.iml
|
||||
*.ipr
|
||||
*.iws
|
||||
.idea/*
|
||||
|
||||
# Visual Studio Code related
|
||||
.classpath
|
||||
.project
|
||||
.settings/
|
||||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
!.vscode/extensions.json
|
||||
|
||||
# Flutter repo-specific
|
||||
/bin/cache/
|
||||
/bin/mingit/
|
||||
/dev/benchmarks/mega_gallery/
|
||||
/dev/bots/.recipe_deps
|
||||
/dev/bots/android_tools/
|
||||
/dev/docs/doc/
|
||||
/dev/docs/flutter.docs.zip
|
||||
/dev/docs/lib/
|
||||
/dev/docs/pubspec.yaml
|
||||
/dev/integration_tests/**/xcuserdata
|
||||
/dev/integration_tests/**/Pods
|
||||
/packages/flutter/coverage/
|
||||
version
|
||||
|
||||
# packages file containing multi-root paths
|
||||
.packages.generated
|
||||
|
||||
# Flutter/Dart/Pub related
|
||||
**/doc/api/
|
||||
**/ios/Flutter/.last_build_id
|
||||
.dart_tool/
|
||||
.flutter-plugins
|
||||
.flutter-plugins-dependencies
|
||||
.packages
|
||||
.pub-cache/
|
||||
.pub/
|
||||
build/
|
||||
flutter_*.png
|
||||
linked_*.ds
|
||||
unlinked.ds
|
||||
unlinked_spec.ds
|
||||
.fvm/
|
||||
|
||||
# Android related
|
||||
**/android/**/gradle-wrapper.jar
|
||||
**/android/.gradle
|
||||
**/android/captures/
|
||||
**/android/gradlew
|
||||
**/android/gradlew.bat
|
||||
**/android/local.properties
|
||||
**/android/**/GeneratedPluginRegistrant.java
|
||||
**/android/key.properties
|
||||
**/android/.idea/
|
||||
*.jks
|
||||
|
||||
# iOS/XCode related
|
||||
**/ios/**/*.mode1v3
|
||||
**/ios/**/*.mode2v3
|
||||
**/ios/**/*.moved-aside
|
||||
**/ios/**/*.pbxuser
|
||||
**/ios/**/*.perspectivev3
|
||||
**/ios/**/*sync/
|
||||
**/ios/**/.sconsign.dblite
|
||||
**/ios/**/.tags*
|
||||
**/ios/**/.vagrant/
|
||||
**/ios/**/DerivedData/
|
||||
**/ios/**/Icon?
|
||||
**/ios/**/Pods/
|
||||
**/ios/**/.symlinks/
|
||||
**/ios/**/profile
|
||||
**/ios/**/xcuserdata
|
||||
**/ios/.generated/
|
||||
**/ios/Flutter/App.framework
|
||||
**/ios/Flutter/Flutter.framework
|
||||
**/ios/Flutter/Flutter.podspec
|
||||
**/ios/Flutter/Generated.xcconfig
|
||||
**/ios/Flutter/app.flx
|
||||
**/ios/Flutter/app.zip
|
||||
**/ios/Flutter/.last_build_id
|
||||
**/ios/Flutter/flutter_assets/
|
||||
**/ios/Flutter/flutter_export_environment.sh
|
||||
**/ios/ServiceDefinitions.json
|
||||
**/ios/Runner/GeneratedPluginRegistrant.*
|
||||
|
||||
# Coverage
|
||||
coverage/
|
||||
|
||||
# Submodules
|
||||
!pubspec.lock
|
||||
packages/**/pubspec.lock
|
||||
|
||||
# Web related
|
||||
lib/generated_plugin_registrant.dart
|
||||
|
||||
# Symbolication related
|
||||
app.*.symbols
|
||||
|
||||
# Obfuscation related
|
||||
app.*.map.json
|
||||
|
||||
# Exceptions to the above rules.
|
||||
!**/ios/**/default.mode1v3
|
||||
!**/ios/**/default.mode2v3
|
||||
!**/ios/**/default.pbxuser
|
||||
!**/ios/**/default.perspectivev3
|
||||
!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
|
||||
!/dev/ci/**/Gemfile.lock
|
||||
!.vscode/extensions.json
|
||||
!.vscode/launch.json
|
||||
!.idea/codeStyles/
|
||||
!.idea/dictionaries/
|
||||
!.idea/runConfigurations/
|
||||
|
||||
# Omit committing pubspec.lock for library packages; see
|
||||
# https://dart.dev/guides/libraries/private-files#pubspeclock.
|
||||
pubspec.lock
|
||||
@@ -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>
|
||||
|
||||
Wyatt Group S.A.S
|
||||
Hugo Pointcheval <git@pcl.ovh>
|
||||
Hugo Pointcheval <hugo.pointcheval@wyattapp.io>
|
||||
Malo Léon <malo.leon@wyattapp.io>
|
||||
@@ -0,0 +1,3 @@
|
||||
# 0.0.1
|
||||
|
||||
- TODO: Describe initial release.
|
||||
@@ -1,55 +1,43 @@
|
||||
<!--
|
||||
* Copyright (C) 2022 WYATT GROUP
|
||||
* Please see the AUTHORS file for details.
|
||||
*
|
||||
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* any later version.
|
||||
*
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
-->
|
||||
|
||||
# Dart - CLI Toolbox
|
||||
|
||||
# Flutter - Wyatt Bloc Layout
|
||||
|
||||
<p align="left">
|
||||
<a href="https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages/src/branch/master/packages/wyatt_analysis">
|
||||
<img src="https://img.shields.io/badge/Style-Wyatt%20Analysis-blue.svg?style=flat-square" alt="Style: Wyatt Analysis" />
|
||||
</a>
|
||||
<img src="https://img.shields.io/badge/SDK-Dart-blue?style=flat-square" alt="SDK: Dart" />
|
||||
<img src="https://img.shields.io/badge/Status-WIP-red?style=flat-square" alt="WIP" />
|
||||
<img src="https://img.shields.io/badge/SDK-Flutter-blue?style=flat-square" alt="SDK: Flutter" />
|
||||
</p>
|
||||
|
||||
Bloc Layout for Flutter.
|
||||
|
||||
|
||||
TODO: Put a short description of the package here that helps potential users
|
||||
know whether this package might be useful for them.
|
||||
|
||||
## Features
|
||||
|
||||
TODO: List what your package can do. Maybe include images, gifs, or videos.
|
||||
<!-- TODO -->
|
||||
|
||||
## Getting started
|
||||
|
||||
TODO: List prerequisites and provide or point to information on how to
|
||||
start using the package.
|
||||
<!-- TODO -->
|
||||
|
||||
## Usage
|
||||
|
||||
TODO: Include short and useful examples for package users. Add longer examples
|
||||
to `/example` folder.
|
||||
|
||||
```dart
|
||||
const like = 'sample';
|
||||
```
|
||||
|
||||
## Additional information
|
||||
|
||||
TODO: Tell users more about the package: where to find more information, how to
|
||||
contribute to the package, how to file issues, what response they can expect
|
||||
from the package authors, and more.
|
||||
<!-- TODO -->
|
||||
@@ -0,0 +1,19 @@
|
||||
# Copyright (C) 2022 WYATT GROUP
|
||||
# Please see the AUTHORS file for details.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
include: package:wyatt_analysis/analysis_options.flutter.experimental.yaml
|
||||
|
||||
@@ -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.
|
||||
|
||||
# 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
|
||||
|
||||
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.
|
||||
# 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
|
||||
# versions available, run `flutter pub outdated`.
|
||||
dependencies:
|
||||
|
||||
flutter:
|
||||
sdk: flutter
|
||||
|
||||
|
||||
wyatt_medium_feeds:
|
||||
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
|
||||
|
||||
wyatt_bloc_layout:
|
||||
path: "../"
|
||||
|
||||
dev_dependencies:
|
||||
|
||||
flutter_test:
|
||||
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
|
||||
# activated in the `analysis_options.yaml` file located at the root of your
|
||||
# package. See that file for information about deactivating specific lint
|
||||
# rules and activating additional ones.
|
||||
flutter_lints: ^2.0.0
|
||||
wyatt_analysis:
|
||||
git:
|
||||
url: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages
|
||||
ref: wyatt_analysis-v2.3.0
|
||||
path: packages/wyatt_analysis
|
||||
|
||||
# For information on the generic Dart part of this file, see the
|
||||
# following page: https://dart.dev/tools/pub/pubspec
|
||||
|
||||
|
||||
# The following section is specific to 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",
|
||||
"short_name": "medium_feeds_example",
|
||||
"name": "example",
|
||||
"short_name": "example",
|
||||
"start_url": ".",
|
||||
"display": "standalone",
|
||||
"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
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
library prompt.framework;
|
||||
export 'presentation/presentation.dart';
|
||||
|
||||
import 'dart:io';
|
||||
import 'package:meta/meta.dart';
|
||||
import 'package:wyatt_cli_toolbox/src/sequences/sequences.dart';
|
||||
import 'package:wyatt_cli_toolbox/src/stylish/stylish.dart';
|
||||
|
||||
part 'build_context.dart';
|
||||
part 'state.dart';
|
||||
part 'widget.dart';
|
||||
export 'package:flutter_bloc/flutter_bloc.dart';
|
||||
export 'package:wyatt_ui_components/wyatt_wyatt_ui_components.dart';
|
||||
export 'package:wyatt_crud_bloc/wyatt_crud_bloc.dart';
|
||||
export 'package:wyatt_ui_layout/wyatt_wyatt_ui_layout.dart';
|
||||
export 'package:wyatt_bloc_helper/wyatt_bloc_helper.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);
|
||||
}
|
||||
}
|
||||