mirror of
https://github.com/Iconica-Development/flutter_registration.git
synced 2025-05-19 13:23:45 +02:00
Compare commits
No commits in common. "master" and "0.1.0" have entirely different histories.
32 changed files with 796 additions and 1461 deletions
10
.github/dependabot.yaml
vendored
10
.github/dependabot.yaml
vendored
|
@ -1,10 +0,0 @@
|
||||||
version: 2
|
|
||||||
updates:
|
|
||||||
- package-ecosystem: "github-actions"
|
|
||||||
directory: "/"
|
|
||||||
schedule:
|
|
||||||
interval: "weekly"
|
|
||||||
- package-ecosystem: "pub"
|
|
||||||
directory: "/"
|
|
||||||
schedule:
|
|
||||||
interval: "daily"
|
|
14
.github/workflows/component-documentation.yml
vendored
14
.github/workflows/component-documentation.yml
vendored
|
@ -1,14 +0,0 @@
|
||||||
name: Iconica Standard Component Documentation Workflow
|
|
||||||
# Workflow Caller version: 1.0.0
|
|
||||||
|
|
||||||
on:
|
|
||||||
release:
|
|
||||||
types: [published]
|
|
||||||
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
call-iconica-component-documentation-workflow:
|
|
||||||
uses: Iconica-Development/.github/.github/workflows/component-documentation.yml@master
|
|
||||||
secrets: inherit
|
|
||||||
permissions: write-all
|
|
32
.github/workflows/flutter.yml
vendored
32
.github/workflows/flutter.yml
vendored
|
@ -1,32 +0,0 @@
|
||||||
name: CI
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [ master ]
|
|
||||||
pull_request:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
- feature/*
|
|
||||||
- bugfix/*
|
|
||||||
- hotfix/*
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
lint:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: |
|
|
||||||
~/.gradle/wrapper
|
|
||||||
/opt/hostedtoolcache/flutter
|
|
||||||
key: ${{ runner.OS }}-flutter-install-cache
|
|
||||||
- uses: subosito/flutter-action@v2
|
|
||||||
with:
|
|
||||||
channel: 'stable'
|
|
||||||
- name: Flutter pub get
|
|
||||||
run: flutter pub get
|
|
||||||
- name: Dart format
|
|
||||||
run: dart format -o none --set-exit-if-changed .
|
|
||||||
- name: Flutter analyze
|
|
||||||
run: flutter analyze
|
|
5
.gitignore
vendored
5
.gitignore
vendored
|
@ -34,8 +34,3 @@ migrate_working_dir/
|
||||||
build/
|
build/
|
||||||
.flutter-plugins
|
.flutter-plugins
|
||||||
.flutter-plugins-dependencies
|
.flutter-plugins-dependencies
|
||||||
.metadata
|
|
||||||
|
|
||||||
# FVM Version Cache
|
|
||||||
.fvm/
|
|
||||||
.fvmrc
|
|
||||||
|
|
76
CHANGELOG.md
76
CHANGELOG.md
|
@ -3,76 +3,12 @@ SPDX-FileCopyrightText: 2022 Iconica
|
||||||
|
|
||||||
SPDX-License-Identifier: GPL-3.0-or-later
|
SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
-->
|
-->
|
||||||
# 3.0.0
|
|
||||||
- fix: fixed the issue with the scrollController when the `pageToReturnTo` is null.
|
|
||||||
- feat: Added default styling and theme.
|
|
||||||
- feat: Added Iconica linter.
|
|
||||||
# 2.0.4
|
|
||||||
- feat: added maxFormWidth to AuthScreen
|
|
||||||
|
|
||||||
# 2.0.3
|
|
||||||
- feat: added default registrationOptions
|
|
||||||
|
|
||||||
# 2.0.2
|
|
||||||
- fix: fixed the issue with values not being saved when calling nextStep.
|
|
||||||
|
|
||||||
# 2.0.1
|
|
||||||
- feat: added circular progress indicator while awaiting registration of user
|
|
||||||
- feat: added alignment option for buttons
|
|
||||||
|
|
||||||
# 2.0.0
|
|
||||||
- feat(buttons): Added the possiblity to only have a next button by return zero on the previous button builder
|
|
||||||
- feat: exposed input decoration in AuthTextField
|
|
||||||
- feat: added title widget and login button builder
|
|
||||||
- feat(bool): Add a boolean field. Can be used for accepting terms and conditions
|
|
||||||
- feat(pass): Add dedicated password screen that manages state internally
|
|
||||||
- fix: Small refactor and brought back the normal alignment for the screens
|
|
||||||
- fix: Fixed alignment and spacing when opening keyboard
|
|
||||||
- feat: add auth drop down field
|
|
||||||
- fix: added step to button builders
|
|
||||||
- fix: exported auth_pass_field
|
|
||||||
- feat: added validation to disable next button
|
|
||||||
- feat(auth-screen): add flexible spacing between fields
|
|
||||||
- fix(keyboard-focus): add unfocus for onPrevious
|
|
||||||
- fix: add empty and required constructors for the RegistrationTranslations
|
|
||||||
|
|
||||||
# 1.2.0
|
|
||||||
|
|
||||||
- feat: Added the ability to have an async register function so you can call it asynchronous.
|
|
||||||
|
|
||||||
# 1.1.0
|
|
||||||
|
|
||||||
- feat: Added the ability to go to specific page on error
|
|
||||||
|
|
||||||
# 1.0.0
|
|
||||||
|
|
||||||
- feat: Added an onError function.
|
|
||||||
- feat: Register function in RegistrationRepository can now return a nullable string. Works like a validator.
|
|
||||||
|
|
||||||
# 0.5.0
|
|
||||||
|
|
||||||
- feat: add customBackgroundColor to AuthScreen
|
|
||||||
- fix: fix linter
|
|
||||||
- fix: fix translations to English
|
|
||||||
|
|
||||||
# 0.4.0
|
|
||||||
|
|
||||||
- feat: Added the abilty to show and hide the passwords
|
|
||||||
|
|
||||||
## 0.3.0
|
|
||||||
|
|
||||||
- Added the abilty to set an initial value fot the default email field
|
|
||||||
|
|
||||||
## 0.2.0
|
|
||||||
|
|
||||||
- Added the abilty to add labels
|
|
||||||
- The default password step now includes two textfields
|
|
||||||
|
|
||||||
## 0.0.2
|
|
||||||
|
|
||||||
- Firebase integration
|
|
||||||
- Registration capabilities
|
|
||||||
|
|
||||||
## 0.0.1
|
## 0.0.1
|
||||||
|
|
||||||
- Initial version
|
* Initial version
|
||||||
|
|
||||||
|
## 0.0.2
|
||||||
|
|
||||||
|
* Firebase integration
|
||||||
|
* Registration capabilities
|
16
README.md
16
README.md
|
@ -1,17 +1,13 @@
|
||||||
[](https://github.com/Iconica-Development) [](https://github.com/Iconica-Development/flutter_registration/actions/new) [](https://github.com/tenhobi/effective_dart)
|
[](https://github.com/Iconica-Development) [](https://github.com/Iconica-Development/flutter_registration/actions/new) [](https://github.com/tenhobi/effective_dart)
|
||||||
|
|
||||||
# Flutter Registration
|
|
||||||
|
|
||||||
Flutter Registration is a package to easily implement
|
Registration plug-in.
|
||||||
a registration flow in your app.
|
|
||||||
|
|
||||||

|
## Install
|
||||||
|
|
||||||
## Setup
|
To use this package, add `flutter_registration` as a [dependency in your pubspec.yaml file](https://flutter.dev/docs/development/platform-integration/platform-channels).
|
||||||
|
|
||||||
To use this package, add `flutter_registration` as a dependency in your pubspec.yaml file.
|
## Configure
|
||||||
|
|
||||||
## How to use
|
|
||||||
|
|
||||||
To configure the registration plug-in use the ```RegistrationScreen``` widget.
|
To configure the registration plug-in use the ```RegistrationScreen``` widget.
|
||||||
|
|
||||||
|
@ -48,8 +44,6 @@ class ExampleRegistrationRepository with RegistrationRepository {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
See the [Example Code](example/lib/main.dart) for an example on how to use this package.
|
|
||||||
|
|
||||||
## Issues
|
## Issues
|
||||||
|
|
||||||
Please file any issues, bugs or feature request as an issue on our [GitHub](https://github.com/Iconica-Development/flutter_registration) page. Commercial support is available if you need help with integration with your app or services. You can contact us at [support@iconica.nl](mailto:support@iconica.nl).
|
Please file any issues, bugs or feature request as an issue on our [GitHub](https://github.com/Iconica-Development/flutter_registration) page. Commercial support is available if you need help with integration with your app or services. You can contact us at [support@iconica.nl](mailto:support@iconica.nl).
|
||||||
|
@ -60,4 +54,4 @@ If you would like to contribute to the plugin (e.g. by improving the documentati
|
||||||
|
|
||||||
## Author
|
## Author
|
||||||
|
|
||||||
This `flutter_registration` for Flutter is developed by [Iconica](https://iconica.nl). You can contact us at <support@iconica.nl>
|
This flutter_registration for Flutter is developed by [Iconica](https://iconica.nl). You can contact us at <support@iconica.nl>
|
|
@ -1,9 +1,218 @@
|
||||||
include: package:flutter_iconica_analysis/components_options.yaml
|
# SPDX-FileCopyrightText: 2022 Iconica
|
||||||
|
#
|
||||||
# Possible to overwrite the rules from the package
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
include: package:flutter_lints/flutter.yaml
|
||||||
analyzer:
|
analyzer:
|
||||||
exclude:
|
errors:
|
||||||
|
todo: ignore
|
||||||
|
exclude: [lib/generated_plugin_registrant.dart]
|
||||||
linter:
|
linter:
|
||||||
|
# https://dart.dev/tools/linter-rules#lints
|
||||||
rules:
|
rules:
|
||||||
|
# error rules
|
||||||
|
always_use_package_imports: false
|
||||||
|
avoid_dynamic_calls: true
|
||||||
|
avoid_empty_else: true
|
||||||
|
avoid_print: true
|
||||||
|
avoid_relative_lib_imports: true
|
||||||
|
avoid_returning_null_for_future: true
|
||||||
|
avoid_slow_async_io: true
|
||||||
|
avoid_type_to_string: true
|
||||||
|
avoid_types_as_parameter_names: true
|
||||||
|
avoid_web_libraries_in_flutter: true
|
||||||
|
cancel_subscriptions: true
|
||||||
|
close_sinks: true
|
||||||
|
comment_references: false
|
||||||
|
control_flow_in_finally: true
|
||||||
|
diagnostic_describe_all_properties: false
|
||||||
|
empty_statements: true
|
||||||
|
hash_and_equals: true
|
||||||
|
invariant_booleans: true
|
||||||
|
iterable_contains_unrelated_type: true
|
||||||
|
list_remove_unrelated_type: true
|
||||||
|
literal_only_boolean_expressions: true
|
||||||
|
no_adjacent_strings_in_list: true
|
||||||
|
no_duplicate_case_values: true
|
||||||
|
no_logic_in_create_state: true
|
||||||
|
prefer_relative_imports: false
|
||||||
|
prefer_void_to_null: true
|
||||||
|
test_types_in_equals: true
|
||||||
|
throw_in_finally: true
|
||||||
|
unnecessary_statements: true
|
||||||
|
unrelated_type_equality_checks: true
|
||||||
|
unsafe_html: true
|
||||||
|
use_build_context_synchronously: true
|
||||||
|
use_key_in_widget_constructors: true
|
||||||
|
valid_regexps: true
|
||||||
|
# style rules
|
||||||
|
always_declare_return_types: true
|
||||||
|
always_put_control_body_on_new_line: true
|
||||||
|
always_put_required_named_parameters_first: true
|
||||||
|
always_require_non_null_named_parameters: true
|
||||||
|
always_specify_types: false
|
||||||
|
annotate_overrides: true
|
||||||
|
avoid_annotating_with_dynamic: false
|
||||||
|
avoid_bool_literals_in_conditional_expressions: true
|
||||||
|
avoid_catches_without_on_clauses: false
|
||||||
|
avoid_catching_errors: false
|
||||||
|
avoid_classes_with_only_static_members: true
|
||||||
|
avoid_double_and_int_checks: true
|
||||||
|
avoid_equals_and_hash_code_on_mutable_classes: false
|
||||||
|
avoid_escaping_inner_quotes: false
|
||||||
|
avoid_field_initializers_in_const_classes: true
|
||||||
|
avoid_final_parameters: true
|
||||||
|
avoid_function_literals_in_foreach_calls: true
|
||||||
|
avoid_implementing_value_types: true
|
||||||
|
avoid_init_to_null: true
|
||||||
|
avoid_js_rounded_ints: true
|
||||||
|
avoid_multiple_declarations_per_line: true
|
||||||
|
avoid_null_checks_in_equality_operators: true
|
||||||
|
avoid_positional_boolean_parameters: true
|
||||||
|
avoid_private_typedef_functions: true
|
||||||
|
avoid_redundant_argument_values: false
|
||||||
|
avoid_renaming_method_parameters: true
|
||||||
|
avoid_return_types_on_setters: true
|
||||||
|
avoid_returning_null: true
|
||||||
|
avoid_returning_null_for_void: true
|
||||||
|
avoid_returning_this: true
|
||||||
|
avoid_setters_without_getters: true
|
||||||
|
avoid_shadowing_type_parameters: true
|
||||||
|
avoid_single_cascade_in_expression_statements: true
|
||||||
|
avoid_types_on_closure_parameters: false
|
||||||
|
avoid_unnecessary_containers: false
|
||||||
|
avoid_unused_constructor_parameters: true
|
||||||
|
avoid_void_async: true
|
||||||
|
await_only_futures: true
|
||||||
|
camel_case_extensions: true
|
||||||
|
camel_case_types: true
|
||||||
|
cascade_invocations: true
|
||||||
|
cast_nullable_to_non_nullable: true
|
||||||
|
conditional_uri_does_not_exist: true
|
||||||
|
constant_identifier_names: true
|
||||||
|
curly_braces_in_flow_control_structures: true
|
||||||
|
deprecated_consistency: true
|
||||||
|
directives_ordering: true
|
||||||
|
do_not_use_environment: true
|
||||||
|
empty_catches: true
|
||||||
|
empty_constructor_bodies: true
|
||||||
|
eol_at_end_of_file: true
|
||||||
|
exhaustive_cases: true
|
||||||
|
file_names: true
|
||||||
|
flutter_style_todos: true
|
||||||
|
implementation_imports: true
|
||||||
|
join_return_with_assignment: true
|
||||||
|
leading_newlines_in_multiline_strings: true
|
||||||
|
library_names: true
|
||||||
|
library_prefixes: true
|
||||||
|
library_private_types_in_public_api: true
|
||||||
|
lines_longer_than_80_chars: true
|
||||||
|
missing_whitespace_between_adjacent_strings: true
|
||||||
|
no_default_cases: true
|
||||||
|
no_leading_underscores_for_library_prefixes: true
|
||||||
|
no_leading_underscores_for_local_identifiers: true
|
||||||
|
no_runtimeType_toString: true
|
||||||
|
non_constant_identifier_names: true
|
||||||
|
noop_primitive_operations: true
|
||||||
|
null_check_on_nullable_type_parameter: true
|
||||||
|
null_closures: true
|
||||||
|
omit_local_variable_types: true
|
||||||
|
one_member_abstracts: true
|
||||||
|
only_throw_errors: true
|
||||||
|
overridden_fields: true
|
||||||
|
package_api_docs: true
|
||||||
|
package_prefixed_library_names: true
|
||||||
|
parameter_assignments: true
|
||||||
|
prefer_adjacent_string_concatenation: true
|
||||||
|
prefer_asserts_in_initializer_lists: true
|
||||||
|
prefer_asserts_with_message: true
|
||||||
|
prefer_collection_literals: true
|
||||||
|
prefer_conditional_assignment: true
|
||||||
|
prefer_const_constructors: true
|
||||||
|
prefer_const_constructors_in_immutables: true
|
||||||
|
prefer_const_declarations: false
|
||||||
|
prefer_const_literals_to_create_immutables: false
|
||||||
|
prefer_constructors_over_static_methods: true
|
||||||
|
prefer_contains: true
|
||||||
|
prefer_double_quotes: false
|
||||||
|
prefer_equal_for_default_values: true
|
||||||
|
prefer_expression_function_bodies: false
|
||||||
|
prefer_final_fields: true
|
||||||
|
prefer_final_in_for_each: false
|
||||||
|
prefer_final_locals: false
|
||||||
|
prefer_final_parameters: false
|
||||||
|
prefer_for_elements_to_map_fromIterable: true
|
||||||
|
prefer_foreach: true
|
||||||
|
prefer_function_declarations_over_variables: true
|
||||||
|
prefer_generic_function_type_aliases: true
|
||||||
|
prefer_if_elements_to_conditional_expressions: true
|
||||||
|
prefer_if_null_operators: true
|
||||||
|
prefer_initializing_formals: true
|
||||||
|
prefer_inlined_adds: true
|
||||||
|
prefer_int_literals: false
|
||||||
|
prefer_interpolation_to_compose_strings: true
|
||||||
|
prefer_is_empty: true
|
||||||
|
prefer_is_not_empty: true
|
||||||
|
prefer_is_not_operator: true
|
||||||
|
prefer_iterable_whereType: true
|
||||||
|
prefer_mixin: true
|
||||||
|
prefer_null_aware_method_calls: true
|
||||||
|
prefer_null_aware_operators: true
|
||||||
|
prefer_single_quotes: true
|
||||||
|
prefer_spread_collections: true
|
||||||
|
prefer_typing_uninitialized_variables: true
|
||||||
|
provide_deprecation_message: true
|
||||||
|
public_member_api_docs: false
|
||||||
|
recursive_getters: true
|
||||||
|
require_trailing_commas: true
|
||||||
|
sized_box_for_whitespace: true
|
||||||
|
sized_box_shrink_expand: true
|
||||||
|
slash_for_doc_comments: true
|
||||||
|
sort_child_properties_last: true
|
||||||
|
sort_constructors_first: true
|
||||||
|
sort_unnamed_constructors_first: true
|
||||||
|
tighten_type_of_initializing_formals: true
|
||||||
|
type_annotate_public_apis: true
|
||||||
|
type_init_formals: true
|
||||||
|
unawaited_futures: true
|
||||||
|
unnecessary_await_in_return: true
|
||||||
|
unnecessary_brace_in_string_interps: true
|
||||||
|
unnecessary_const: false
|
||||||
|
unnecessary_constructor_name: true
|
||||||
|
unnecessary_final: true
|
||||||
|
unnecessary_getters_setters: true
|
||||||
|
unnecessary_lambdas: true
|
||||||
|
unnecessary_late: true
|
||||||
|
unnecessary_new: true
|
||||||
|
unnecessary_null_aware_assignments: true
|
||||||
|
unnecessary_null_checks: true
|
||||||
|
unnecessary_null_in_if_null_operators: true
|
||||||
|
unnecessary_nullable_for_final_variable_declarations: true
|
||||||
|
unnecessary_overrides: true
|
||||||
|
unnecessary_parenthesis: true
|
||||||
|
unnecessary_raw_strings: true
|
||||||
|
unnecessary_string_escapes: true
|
||||||
|
unnecessary_string_interpolations: true
|
||||||
|
unnecessary_this: true
|
||||||
|
use_decorated_box: true
|
||||||
|
use_full_hex_values_for_flutter_colors: true
|
||||||
|
use_function_type_syntax_for_parameters: true
|
||||||
|
use_if_null_to_convert_nulls_to_bools: true
|
||||||
|
use_is_even_rather_than_modulo: true
|
||||||
|
use_late_for_private_fields_and_variables: true
|
||||||
|
use_named_constants: true
|
||||||
|
use_raw_strings: false
|
||||||
|
use_rethrow_when_possible: true
|
||||||
|
use_setters_to_change_properties: true
|
||||||
|
use_string_buffers: true
|
||||||
|
use_test_throws_matchers: true
|
||||||
|
use_to_and_as_if_applicable: true
|
||||||
|
void_checks: true
|
||||||
|
# pub rules
|
||||||
|
depend_on_referenced_packages: true
|
||||||
|
lowercase_with_underscores: true
|
||||||
|
secure_pubspec_urls: false
|
||||||
|
sort_pub_dependencies: false
|
||||||
|
|
||||||
|
# Additional information about this file can be found at
|
||||||
|
# https://dart.dev/guides/language/analysis-options
|
||||||
|
|
48
bitbucket-pipelines.yml
Normal file
48
bitbucket-pipelines.yml
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
# SPDX-FileCopyrightText: 2022 Iconica
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
image: cirrusci/flutter
|
||||||
|
|
||||||
|
pipelines:
|
||||||
|
pull-requests:
|
||||||
|
feature/*:
|
||||||
|
- step:
|
||||||
|
caches:
|
||||||
|
- gradle
|
||||||
|
- gradlewrapper
|
||||||
|
- flutter
|
||||||
|
name: Run analyzer & test
|
||||||
|
script:
|
||||||
|
- flutter pub get
|
||||||
|
- flutter format -o none --set-exit-if-changed .
|
||||||
|
- flutter analyze
|
||||||
|
|
||||||
|
develop:
|
||||||
|
- step:
|
||||||
|
caches:
|
||||||
|
- gradle
|
||||||
|
- gradlewrapper
|
||||||
|
- flutter
|
||||||
|
name: Run analyzer & test
|
||||||
|
script:
|
||||||
|
- flutter pub get
|
||||||
|
- flutter format -o none --set-exit-if-changed .
|
||||||
|
- flutter analyze
|
||||||
|
|
||||||
|
hotfix/*:
|
||||||
|
- step:
|
||||||
|
caches:
|
||||||
|
- gradle
|
||||||
|
- gradlewrapper
|
||||||
|
- flutter
|
||||||
|
name: Run analyzer & test
|
||||||
|
script:
|
||||||
|
- flutter pub get
|
||||||
|
- flutter format -o none --set-exit-if-changed .
|
||||||
|
- flutter analyze
|
||||||
|
|
||||||
|
definitions:
|
||||||
|
caches:
|
||||||
|
gradlewrapper: ~/.gradle/wrapper
|
||||||
|
flutter: ~/.pub-cache
|
|
@ -1,4 +1,218 @@
|
||||||
|
# SPDX-FileCopyrightText: 2022 Iconica
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
include: package:flutter_lints/flutter.yaml
|
include: package:flutter_lints/flutter.yaml
|
||||||
|
analyzer:
|
||||||
|
errors:
|
||||||
|
todo: ignore
|
||||||
|
exclude: [lib/generated_plugin_registrant.dart]
|
||||||
|
linter:
|
||||||
|
# https://dart.dev/tools/linter-rules#lints
|
||||||
|
rules:
|
||||||
|
# error rules
|
||||||
|
always_use_package_imports: false
|
||||||
|
avoid_dynamic_calls: true
|
||||||
|
avoid_empty_else: true
|
||||||
|
avoid_print: true
|
||||||
|
avoid_relative_lib_imports: true
|
||||||
|
avoid_returning_null_for_future: true
|
||||||
|
avoid_slow_async_io: true
|
||||||
|
avoid_type_to_string: true
|
||||||
|
avoid_types_as_parameter_names: true
|
||||||
|
avoid_web_libraries_in_flutter: true
|
||||||
|
cancel_subscriptions: true
|
||||||
|
close_sinks: true
|
||||||
|
comment_references: false
|
||||||
|
control_flow_in_finally: true
|
||||||
|
diagnostic_describe_all_properties: false
|
||||||
|
empty_statements: true
|
||||||
|
hash_and_equals: true
|
||||||
|
invariant_booleans: true
|
||||||
|
iterable_contains_unrelated_type: true
|
||||||
|
list_remove_unrelated_type: true
|
||||||
|
literal_only_boolean_expressions: true
|
||||||
|
no_adjacent_strings_in_list: true
|
||||||
|
no_duplicate_case_values: true
|
||||||
|
no_logic_in_create_state: true
|
||||||
|
prefer_relative_imports: false
|
||||||
|
prefer_void_to_null: true
|
||||||
|
test_types_in_equals: true
|
||||||
|
throw_in_finally: true
|
||||||
|
unnecessary_statements: true
|
||||||
|
unrelated_type_equality_checks: true
|
||||||
|
unsafe_html: true
|
||||||
|
use_build_context_synchronously: true
|
||||||
|
use_key_in_widget_constructors: true
|
||||||
|
valid_regexps: true
|
||||||
|
# style rules
|
||||||
|
always_declare_return_types: true
|
||||||
|
always_put_control_body_on_new_line: true
|
||||||
|
always_put_required_named_parameters_first: true
|
||||||
|
always_require_non_null_named_parameters: true
|
||||||
|
always_specify_types: false
|
||||||
|
annotate_overrides: true
|
||||||
|
avoid_annotating_with_dynamic: false
|
||||||
|
avoid_bool_literals_in_conditional_expressions: true
|
||||||
|
avoid_catches_without_on_clauses: false
|
||||||
|
avoid_catching_errors: false
|
||||||
|
avoid_classes_with_only_static_members: true
|
||||||
|
avoid_double_and_int_checks: true
|
||||||
|
avoid_equals_and_hash_code_on_mutable_classes: false
|
||||||
|
avoid_escaping_inner_quotes: false
|
||||||
|
avoid_field_initializers_in_const_classes: true
|
||||||
|
avoid_final_parameters: true
|
||||||
|
avoid_function_literals_in_foreach_calls: true
|
||||||
|
avoid_implementing_value_types: true
|
||||||
|
avoid_init_to_null: true
|
||||||
|
avoid_js_rounded_ints: true
|
||||||
|
avoid_multiple_declarations_per_line: true
|
||||||
|
avoid_null_checks_in_equality_operators: true
|
||||||
|
avoid_positional_boolean_parameters: true
|
||||||
|
avoid_private_typedef_functions: true
|
||||||
|
avoid_redundant_argument_values: false
|
||||||
|
avoid_renaming_method_parameters: true
|
||||||
|
avoid_return_types_on_setters: true
|
||||||
|
avoid_returning_null: true
|
||||||
|
avoid_returning_null_for_void: true
|
||||||
|
avoid_returning_this: true
|
||||||
|
avoid_setters_without_getters: true
|
||||||
|
avoid_shadowing_type_parameters: true
|
||||||
|
avoid_single_cascade_in_expression_statements: true
|
||||||
|
avoid_types_on_closure_parameters: false
|
||||||
|
avoid_unnecessary_containers: false
|
||||||
|
avoid_unused_constructor_parameters: true
|
||||||
|
avoid_void_async: true
|
||||||
|
await_only_futures: true
|
||||||
|
camel_case_extensions: true
|
||||||
|
camel_case_types: true
|
||||||
|
cascade_invocations: true
|
||||||
|
cast_nullable_to_non_nullable: true
|
||||||
|
conditional_uri_does_not_exist: true
|
||||||
|
constant_identifier_names: true
|
||||||
|
curly_braces_in_flow_control_structures: true
|
||||||
|
deprecated_consistency: true
|
||||||
|
directives_ordering: true
|
||||||
|
do_not_use_environment: true
|
||||||
|
empty_catches: true
|
||||||
|
empty_constructor_bodies: true
|
||||||
|
eol_at_end_of_file: true
|
||||||
|
exhaustive_cases: true
|
||||||
|
file_names: true
|
||||||
|
flutter_style_todos: true
|
||||||
|
implementation_imports: true
|
||||||
|
join_return_with_assignment: true
|
||||||
|
leading_newlines_in_multiline_strings: true
|
||||||
|
library_names: true
|
||||||
|
library_prefixes: true
|
||||||
|
library_private_types_in_public_api: true
|
||||||
|
lines_longer_than_80_chars: true
|
||||||
|
missing_whitespace_between_adjacent_strings: true
|
||||||
|
no_default_cases: true
|
||||||
|
no_leading_underscores_for_library_prefixes: true
|
||||||
|
no_leading_underscores_for_local_identifiers: true
|
||||||
|
no_runtimeType_toString: true
|
||||||
|
non_constant_identifier_names: true
|
||||||
|
noop_primitive_operations: true
|
||||||
|
null_check_on_nullable_type_parameter: true
|
||||||
|
null_closures: true
|
||||||
|
omit_local_variable_types: true
|
||||||
|
one_member_abstracts: true
|
||||||
|
only_throw_errors: true
|
||||||
|
overridden_fields: true
|
||||||
|
package_api_docs: true
|
||||||
|
package_prefixed_library_names: true
|
||||||
|
parameter_assignments: true
|
||||||
|
prefer_adjacent_string_concatenation: true
|
||||||
|
prefer_asserts_in_initializer_lists: true
|
||||||
|
prefer_asserts_with_message: true
|
||||||
|
prefer_collection_literals: true
|
||||||
|
prefer_conditional_assignment: true
|
||||||
|
prefer_const_constructors: true
|
||||||
|
prefer_const_constructors_in_immutables: true
|
||||||
|
prefer_const_declarations: false
|
||||||
|
prefer_const_literals_to_create_immutables: false
|
||||||
|
prefer_constructors_over_static_methods: true
|
||||||
|
prefer_contains: true
|
||||||
|
prefer_double_quotes: false
|
||||||
|
prefer_equal_for_default_values: true
|
||||||
|
prefer_expression_function_bodies: false
|
||||||
|
prefer_final_fields: true
|
||||||
|
prefer_final_in_for_each: false
|
||||||
|
prefer_final_locals: false
|
||||||
|
prefer_final_parameters: false
|
||||||
|
prefer_for_elements_to_map_fromIterable: true
|
||||||
|
prefer_foreach: true
|
||||||
|
prefer_function_declarations_over_variables: true
|
||||||
|
prefer_generic_function_type_aliases: true
|
||||||
|
prefer_if_elements_to_conditional_expressions: true
|
||||||
|
prefer_if_null_operators: true
|
||||||
|
prefer_initializing_formals: true
|
||||||
|
prefer_inlined_adds: true
|
||||||
|
prefer_int_literals: false
|
||||||
|
prefer_interpolation_to_compose_strings: true
|
||||||
|
prefer_is_empty: true
|
||||||
|
prefer_is_not_empty: true
|
||||||
|
prefer_is_not_operator: true
|
||||||
|
prefer_iterable_whereType: true
|
||||||
|
prefer_mixin: true
|
||||||
|
prefer_null_aware_method_calls: true
|
||||||
|
prefer_null_aware_operators: true
|
||||||
|
prefer_single_quotes: true
|
||||||
|
prefer_spread_collections: true
|
||||||
|
prefer_typing_uninitialized_variables: true
|
||||||
|
provide_deprecation_message: true
|
||||||
|
public_member_api_docs: false
|
||||||
|
recursive_getters: true
|
||||||
|
require_trailing_commas: true
|
||||||
|
sized_box_for_whitespace: true
|
||||||
|
sized_box_shrink_expand: true
|
||||||
|
slash_for_doc_comments: true
|
||||||
|
sort_child_properties_last: true
|
||||||
|
sort_constructors_first: true
|
||||||
|
sort_unnamed_constructors_first: true
|
||||||
|
tighten_type_of_initializing_formals: true
|
||||||
|
type_annotate_public_apis: true
|
||||||
|
type_init_formals: true
|
||||||
|
unawaited_futures: true
|
||||||
|
unnecessary_await_in_return: true
|
||||||
|
unnecessary_brace_in_string_interps: true
|
||||||
|
unnecessary_const: false
|
||||||
|
unnecessary_constructor_name: true
|
||||||
|
unnecessary_final: true
|
||||||
|
unnecessary_getters_setters: true
|
||||||
|
unnecessary_lambdas: true
|
||||||
|
unnecessary_late: true
|
||||||
|
unnecessary_new: true
|
||||||
|
unnecessary_null_aware_assignments: true
|
||||||
|
unnecessary_null_checks: true
|
||||||
|
unnecessary_null_in_if_null_operators: true
|
||||||
|
unnecessary_nullable_for_final_variable_declarations: true
|
||||||
|
unnecessary_overrides: true
|
||||||
|
unnecessary_parenthesis: true
|
||||||
|
unnecessary_raw_strings: true
|
||||||
|
unnecessary_string_escapes: true
|
||||||
|
unnecessary_string_interpolations: true
|
||||||
|
unnecessary_this: true
|
||||||
|
use_decorated_box: true
|
||||||
|
use_full_hex_values_for_flutter_colors: true
|
||||||
|
use_function_type_syntax_for_parameters: true
|
||||||
|
use_if_null_to_convert_nulls_to_bools: true
|
||||||
|
use_is_even_rather_than_modulo: true
|
||||||
|
use_late_for_private_fields_and_variables: true
|
||||||
|
use_named_constants: true
|
||||||
|
use_raw_strings: false
|
||||||
|
use_rethrow_when_possible: true
|
||||||
|
use_setters_to_change_properties: true
|
||||||
|
use_string_buffers: true
|
||||||
|
use_test_throws_matchers: true
|
||||||
|
use_to_and_as_if_applicable: true
|
||||||
|
void_checks: true
|
||||||
|
# pub rules
|
||||||
|
depend_on_referenced_packages: true
|
||||||
|
lowercase_with_underscores: true
|
||||||
|
secure_pubspec_urls: false
|
||||||
|
sort_pub_dependencies: false
|
||||||
|
|
||||||
# Additional information about this file can be found at
|
# Additional information about this file can be found at
|
||||||
# https://dart.dev/guides/language/analysis-options
|
# https://dart.dev/guides/language/analysis-options
|
|
@ -26,6 +26,6 @@ subprojects {
|
||||||
project.evaluationDependsOn(':app')
|
project.evaluationDependsOn(':app')
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.register("clean", Delete) {
|
task clean(type: Delete) {
|
||||||
delete rootProject.buildDir
|
delete rootProject.buildDir
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# Uncomment this line to define a global platform for your project
|
# Uncomment this line to define a global platform for your project
|
||||||
platform :ios, '11.0'
|
# platform :ios, '11.0'
|
||||||
|
|
||||||
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
|
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
|
||||||
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
|
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
|
||||||
|
|
|
@ -9,8 +9,8 @@ import 'package:flutter_registration/flutter_registration.dart';
|
||||||
|
|
||||||
class ExampleRegistrationRepository with RegistrationRepository {
|
class ExampleRegistrationRepository with RegistrationRepository {
|
||||||
@override
|
@override
|
||||||
Future<String?> register(HashMap values) {
|
Future<bool> register(HashMap values) {
|
||||||
debugPrint('register: $values');
|
debugPrint('register: $values');
|
||||||
return Future.value(null);
|
return Future.value(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,81 +2,27 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: BSD-3-Clause
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
import 'package:flutter/gestures.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_registration/flutter_registration.dart';
|
import 'package:flutter_registration/flutter_registration.dart';
|
||||||
import 'example_registration_repository.dart';
|
import 'example_registration_repository.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
runApp(
|
runApp(
|
||||||
MaterialApp(
|
const MaterialApp(
|
||||||
theme: ThemeData(
|
home: FlutterRegistrationDemo(),
|
||||||
inputDecorationTheme: const InputDecorationTheme(
|
|
||||||
errorStyle: TextStyle(color: Colors.red),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
home: const FlutterRegistrationDemo(),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
class FlutterRegistrationDemo extends StatefulWidget {
|
class FlutterRegistrationDemo extends StatelessWidget {
|
||||||
const FlutterRegistrationDemo({super.key});
|
const FlutterRegistrationDemo({Key? key}) : super(key: key);
|
||||||
|
|
||||||
@override
|
|
||||||
State<FlutterRegistrationDemo> createState() =>
|
|
||||||
_FlutterRegistrationDemoState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _FlutterRegistrationDemoState extends State<FlutterRegistrationDemo> {
|
|
||||||
late List<AuthStep> steps;
|
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
super.initState();
|
|
||||||
|
|
||||||
steps = RegistrationOptions.getDefaultSteps();
|
|
||||||
|
|
||||||
steps[1].fields.add(
|
|
||||||
AuthBoolField(
|
|
||||||
name: 'termsConditions',
|
|
||||||
widgetType: BoolWidgetType.checkbox,
|
|
||||||
validators: [
|
|
||||||
(value) {
|
|
||||||
if (value == null || !value) {
|
|
||||||
return 'Required';
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
],
|
|
||||||
rightWidget: Text.rich(
|
|
||||||
TextSpan(
|
|
||||||
text: 'I agree with the ',
|
|
||||||
children: <TextSpan>[
|
|
||||||
TextSpan(
|
|
||||||
text: 'terms & conditions',
|
|
||||||
style: const TextStyle(
|
|
||||||
decoration: TextDecoration.underline,
|
|
||||||
),
|
|
||||||
recognizer: TapGestureRecognizer()
|
|
||||||
..onTap = () {
|
|
||||||
debugPrint('Open terms and conditions');
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return RegistrationScreen(
|
return RegistrationScreen(
|
||||||
registrationOptions: RegistrationOptions(
|
registrationOptions: RegistrationOptions(
|
||||||
registrationRepository: ExampleRegistrationRepository(),
|
registrationRepository: ExampleRegistrationRepository(),
|
||||||
registrationSteps: steps,
|
registrationSteps: RegistrationOptions.getDefaultSteps(),
|
||||||
afterRegistration: () {
|
afterRegistration: () {
|
||||||
debugPrint('Registered!');
|
debugPrint('Registered!');
|
||||||
},
|
},
|
||||||
|
@ -86,7 +32,8 @@ class _FlutterRegistrationDemoState extends State<FlutterRegistrationDemo> {
|
||||||
}
|
}
|
||||||
|
|
||||||
class ProtectedScreen extends StatelessWidget {
|
class ProtectedScreen extends StatelessWidget {
|
||||||
const ProtectedScreen({super.key});
|
const ProtectedScreen({Key? key}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return const Scaffold(
|
return const Scaffold(
|
||||||
|
|
|
@ -5,56 +5,49 @@ packages:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: async
|
name: async
|
||||||
sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c"
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.11.0"
|
version: "2.9.0"
|
||||||
boolean_selector:
|
boolean_selector:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: boolean_selector
|
name: boolean_selector
|
||||||
sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66"
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.1"
|
version: "2.1.0"
|
||||||
characters:
|
characters:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: characters
|
name: characters
|
||||||
sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605"
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.3.0"
|
version: "1.2.1"
|
||||||
clock:
|
clock:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: clock
|
name: clock
|
||||||
sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.1"
|
version: "1.1.1"
|
||||||
collection:
|
collection:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: collection
|
name: collection
|
||||||
sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.18.0"
|
version: "1.16.0"
|
||||||
cupertino_icons:
|
cupertino_icons:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: cupertino_icons
|
name: cupertino_icons
|
||||||
sha256: d57953e10f9f8327ce64a508a355f0b1ec902193f66288e8cb5070e7c47eeb2d
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.6"
|
version: "1.0.5"
|
||||||
fake_async:
|
fake_async:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: fake_async
|
name: fake_async
|
||||||
sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78"
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.3.1"
|
version: "1.3.1"
|
||||||
flutter:
|
flutter:
|
||||||
|
@ -62,22 +55,20 @@ packages:
|
||||||
description: flutter
|
description: flutter
|
||||||
source: sdk
|
source: sdk
|
||||||
version: "0.0.0"
|
version: "0.0.0"
|
||||||
flutter_input_library:
|
flutter_hooks:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: flutter_input_library
|
name: flutter_hooks
|
||||||
sha256: db8d9d57c31f166ed7c4ec3d060d18891533c57877a30c6c2668231efa1a44f8
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://forgejo.internal.iconica.nl/api/packages/internal/pub/"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.6.0"
|
version: "0.18.5+1"
|
||||||
flutter_lints:
|
flutter_lints:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
name: flutter_lints
|
name: flutter_lints
|
||||||
sha256: a25a15ebbdfc33ab1cd26c63a6ee519df92338a9c10f122adda92938253bef04
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.3"
|
version: "2.0.1"
|
||||||
flutter_localizations:
|
flutter_localizations:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description: flutter
|
description: flutter
|
||||||
|
@ -89,7 +80,7 @@ packages:
|
||||||
path: ".."
|
path: ".."
|
||||||
relative: true
|
relative: true
|
||||||
source: path
|
source: path
|
||||||
version: "2.0.4"
|
version: "0.1.0"
|
||||||
flutter_test:
|
flutter_test:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description: flutter
|
description: flutter
|
||||||
|
@ -99,74 +90,44 @@ packages:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: intl
|
name: intl
|
||||||
sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.19.0"
|
version: "0.17.0"
|
||||||
leak_tracker:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: leak_tracker
|
|
||||||
sha256: "7f0df31977cb2c0b88585095d168e689669a2cc9b97c309665e3386f3e9d341a"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "10.0.4"
|
|
||||||
leak_tracker_flutter_testing:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: leak_tracker_flutter_testing
|
|
||||||
sha256: "06e98f569d004c1315b991ded39924b21af84cf14cc94791b8aea337d25b57f8"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "3.0.3"
|
|
||||||
leak_tracker_testing:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: leak_tracker_testing
|
|
||||||
sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "3.0.1"
|
|
||||||
lints:
|
lints:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: lints
|
name: lints
|
||||||
sha256: "0a217c6c989d21039f1498c3ed9f3ed71b354e69873f13a8dfc3c9fe76f1b452"
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.1"
|
version: "2.0.0"
|
||||||
matcher:
|
matcher:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: matcher
|
name: matcher
|
||||||
sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.12.16+1"
|
version: "0.12.12"
|
||||||
material_color_utilities:
|
material_color_utilities:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: material_color_utilities
|
name: material_color_utilities
|
||||||
sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a"
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.8.0"
|
version: "0.1.5"
|
||||||
meta:
|
meta:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: meta
|
name: meta
|
||||||
sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136"
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.12.0"
|
version: "1.8.0"
|
||||||
path:
|
path:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: path
|
name: path
|
||||||
sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af"
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.9.0"
|
version: "1.8.2"
|
||||||
sky_engine:
|
sky_engine:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description: flutter
|
description: flutter
|
||||||
|
@ -176,66 +137,51 @@ packages:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: source_span
|
name: source_span
|
||||||
sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.10.0"
|
version: "1.9.0"
|
||||||
stack_trace:
|
stack_trace:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: stack_trace
|
name: stack_trace
|
||||||
sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b"
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.11.1"
|
version: "1.10.0"
|
||||||
stream_channel:
|
stream_channel:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: stream_channel
|
name: stream_channel
|
||||||
sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.2"
|
version: "2.1.0"
|
||||||
string_scanner:
|
string_scanner:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: string_scanner
|
name: string_scanner
|
||||||
sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde"
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.2.0"
|
version: "1.1.1"
|
||||||
term_glyph:
|
term_glyph:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: term_glyph
|
name: term_glyph
|
||||||
sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.2.1"
|
version: "1.2.1"
|
||||||
test_api:
|
test_api:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: test_api
|
name: test_api
|
||||||
sha256: "9955ae474176f7ac8ee4e989dadfb411a58c30415bcfb648fa04b2b8a03afa7f"
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.7.0"
|
version: "0.4.12"
|
||||||
vector_math:
|
vector_math:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: vector_math
|
name: vector_math
|
||||||
sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803"
|
url: "https://pub.dartlang.org"
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.4"
|
version: "2.1.2"
|
||||||
vm_service:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: vm_service
|
|
||||||
sha256: "3923c89304b715fb1eb6423f017651664a03bf5f4b29983627c4da791f74a4ec"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "14.2.1"
|
|
||||||
sdks:
|
sdks:
|
||||||
dart: ">=3.3.0 <4.0.0"
|
dart: ">=2.18.0 <3.0.0"
|
||||||
flutter: ">=3.18.0-18.0.pre.54"
|
flutter: ">=3.0.0"
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 692 KiB |
|
@ -1,21 +1,14 @@
|
||||||
// SPDX-FileCopyrightText: 2022 Iconica
|
// SPDX-FileCopyrightText: 2022 Iconica
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: BSD-3-Clause
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
/// Flutter registration component that provides a registration
|
|
||||||
/// screen with multiple registration steps.
|
|
||||||
library flutter_registration;
|
library flutter_registration;
|
||||||
|
|
||||||
export "package:flutter_input_library/flutter_input_library.dart"
|
export 'src/config/registration_options.dart';
|
||||||
show BoolWidgetType;
|
export 'src/config/registration_translations.dart';
|
||||||
|
export 'src/model/auth_exception.dart';
|
||||||
export "src/config/registration_options.dart";
|
export 'src/model/auth_field.dart';
|
||||||
export "src/config/registration_translations.dart";
|
export 'src/model/auth_step.dart';
|
||||||
export "src/model/auth_bool_field.dart";
|
export 'src/model/auth_text_field.dart';
|
||||||
export "src/model/auth_drop_down.dart";
|
export 'src/registration_screen.dart';
|
||||||
export "src/model/auth_exception.dart";
|
export 'src/service/registration_repository.dart';
|
||||||
export "src/model/auth_field.dart";
|
|
||||||
export "src/model/auth_pass_field.dart";
|
|
||||||
export "src/model/auth_step.dart";
|
|
||||||
export "src/model/auth_text_field.dart";
|
|
||||||
export "src/registration_screen.dart";
|
|
||||||
export "src/service/registration_repository.dart";
|
|
||||||
|
|
|
@ -2,181 +2,140 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: BSD-3-Clause
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
import "dart:async";
|
import 'dart:collection';
|
||||||
import "dart:collection";
|
import 'package:flutter/material.dart';
|
||||||
import "package:flutter/material.dart";
|
import 'package:flutter_registration/src/model/auth_field.dart';
|
||||||
import "package:flutter_registration/flutter_registration.dart";
|
import 'package:flutter_registration/src/model/auth_step.dart';
|
||||||
|
|
||||||
/// A widget for handling multi-step authentication processes.
|
|
||||||
class AuthScreen extends StatefulWidget {
|
class AuthScreen extends StatefulWidget {
|
||||||
/// Constructs an [AuthScreen] object.
|
|
||||||
///
|
|
||||||
/// [appBarTitle] specifies the title of the app bar.
|
|
||||||
///
|
|
||||||
/// [onFinish] is a function called upon
|
|
||||||
/// completion of the authentication process.
|
|
||||||
///
|
|
||||||
/// [steps] is a list of authentication steps to be completed.
|
|
||||||
///
|
|
||||||
/// [submitBtnTitle] specifies the title of the submit button.
|
|
||||||
///
|
|
||||||
/// [nextBtnTitle] specifies the title of the next button.
|
|
||||||
///
|
|
||||||
/// [previousBtnTitle] specifies the title of the previous button.
|
|
||||||
///
|
|
||||||
/// [customAppBar] allows customization of the app bar.
|
|
||||||
///
|
|
||||||
/// [buttonMainAxisAlignment] specifies the alignment of the buttons.
|
|
||||||
///
|
|
||||||
/// [customBackgroundColor] allows customization of the background color.
|
|
||||||
///
|
|
||||||
/// [nextButtonBuilder] allows customization of the next button.
|
|
||||||
///
|
|
||||||
/// [previousButtonBuilder] allows customization of the previous button.
|
|
||||||
///
|
|
||||||
/// [titleWidget] specifies a custom widget
|
|
||||||
/// to be displayed at the top of the screen.
|
|
||||||
///
|
|
||||||
/// [loginButton] specifies a custom login button widget.
|
|
||||||
///
|
|
||||||
/// [titleFlex] specifies the flex value for the title widget.
|
|
||||||
///
|
|
||||||
/// [formFlex] specifies the flex value for the form widget.
|
|
||||||
///
|
|
||||||
/// [beforeTitleFlex] specifies the flex value before the title widget.
|
|
||||||
///
|
|
||||||
/// [afterTitleFlex] specifies the flex value after the title widget.
|
|
||||||
|
|
||||||
const AuthScreen({
|
const AuthScreen({
|
||||||
required this.appBarTitle,
|
required this.title,
|
||||||
required this.steps,
|
required this.steps,
|
||||||
required this.submitBtnTitle,
|
required this.submitBtnTitle,
|
||||||
required this.nextBtnTitle,
|
required this.nextBtnTitle,
|
||||||
required this.previousBtnTitle,
|
required this.previousBtnTitle,
|
||||||
required this.onFinish,
|
required this.onFinish,
|
||||||
this.customAppBar,
|
this.customAppBar,
|
||||||
this.buttonMainAxisAlignment,
|
|
||||||
this.customBackgroundColor,
|
|
||||||
this.nextButtonBuilder,
|
|
||||||
this.previousButtonBuilder,
|
|
||||||
this.titleWidget,
|
|
||||||
this.loginButton,
|
|
||||||
this.titleFlex,
|
|
||||||
this.formFlex,
|
|
||||||
this.beforeTitleFlex,
|
|
||||||
this.afterTitleFlex,
|
|
||||||
this.maxFormWidth,
|
|
||||||
super.key,
|
super.key,
|
||||||
}) : assert(steps.length > 0, "At least one step is required");
|
}) : assert(steps.length > 0, 'At least one step is required');
|
||||||
|
|
||||||
/// The title of the app bar.
|
final String title;
|
||||||
final String appBarTitle;
|
final Function({
|
||||||
|
required HashMap<String, String> values,
|
||||||
/// A function called upon completion of the authentication process.
|
required VoidCallback onError,
|
||||||
final Future<void> Function({
|
|
||||||
required HashMap<String, dynamic> values,
|
|
||||||
required void Function(int? pageToReturn) onError,
|
|
||||||
}) onFinish;
|
}) onFinish;
|
||||||
|
|
||||||
/// The authentication steps to be completed.
|
|
||||||
final List<AuthStep> steps;
|
final List<AuthStep> steps;
|
||||||
|
|
||||||
/// The title of the submit button.
|
|
||||||
final String submitBtnTitle;
|
final String submitBtnTitle;
|
||||||
|
|
||||||
/// The title of the next button.
|
|
||||||
final String nextBtnTitle;
|
final String nextBtnTitle;
|
||||||
|
|
||||||
/// The title of the previous button.
|
|
||||||
final String previousBtnTitle;
|
final String previousBtnTitle;
|
||||||
|
|
||||||
/// A custom app bar widget.
|
|
||||||
final AppBar? customAppBar;
|
final AppBar? customAppBar;
|
||||||
|
|
||||||
/// The alignment of the buttons.
|
|
||||||
final MainAxisAlignment? buttonMainAxisAlignment;
|
|
||||||
|
|
||||||
/// The background color of the screen.
|
|
||||||
final Color? customBackgroundColor;
|
|
||||||
|
|
||||||
/// A custom widget for the button.
|
|
||||||
final Widget Function(
|
|
||||||
Future<void> Function()? onPressed,
|
|
||||||
String label,
|
|
||||||
int step,
|
|
||||||
// ignore: avoid_positional_boolean_parameters
|
|
||||||
bool enabled,
|
|
||||||
)? nextButtonBuilder;
|
|
||||||
|
|
||||||
/// A custom widget for the button.
|
|
||||||
final Widget? Function(VoidCallback onPressed, String label, int step)?
|
|
||||||
previousButtonBuilder;
|
|
||||||
|
|
||||||
/// A custom widget for the title.
|
|
||||||
final Widget? titleWidget;
|
|
||||||
|
|
||||||
/// A custom widget for the login button.
|
|
||||||
final Widget? loginButton;
|
|
||||||
|
|
||||||
/// The flex value for the title widget.
|
|
||||||
final int? titleFlex;
|
|
||||||
|
|
||||||
/// The flex value for the form widget.
|
|
||||||
final int? formFlex;
|
|
||||||
|
|
||||||
/// The flex value before the title widget.
|
|
||||||
final int? beforeTitleFlex;
|
|
||||||
|
|
||||||
/// The flex value after the title widget.
|
|
||||||
final int? afterTitleFlex;
|
|
||||||
|
|
||||||
/// The maximum width of the form.
|
|
||||||
final double? maxFormWidth;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<AuthScreen> createState() => _AuthScreenState();
|
State<AuthScreen> createState() => _AuthScreenState();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The state for [AuthScreen].
|
|
||||||
class _AuthScreenState extends State<AuthScreen> {
|
class _AuthScreenState extends State<AuthScreen> {
|
||||||
final _formKey = GlobalKey<FormState>();
|
final _formKey = GlobalKey<FormState>();
|
||||||
final _pageController = PageController();
|
final _pageController = PageController();
|
||||||
final _animationDuration = const Duration(milliseconds: 300);
|
final _animationDuration = const Duration(milliseconds: 300);
|
||||||
final _animationCurve = Curves.ease;
|
final _animationCurve = Curves.ease;
|
||||||
bool _formValid = false;
|
|
||||||
|
|
||||||
/// Gets the app bar.
|
|
||||||
AppBar get _appBar =>
|
AppBar get _appBar =>
|
||||||
widget.customAppBar ??
|
widget.customAppBar ??
|
||||||
AppBar(
|
AppBar(
|
||||||
backgroundColor: const Color(0xffFAF9F6),
|
title: Text(widget.title),
|
||||||
title: Text(widget.appBarTitle),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
/// Handles previous button press.
|
@override
|
||||||
void onPrevious() {
|
Widget build(BuildContext context) => Scaffold(
|
||||||
FocusScope.of(context).unfocus();
|
backgroundColor: Theme.of(context).backgroundColor,
|
||||||
_validate(_pageController.page!.toInt() - 1);
|
appBar: _appBar,
|
||||||
unawaited(
|
body: Form(
|
||||||
_pageController.previousPage(
|
key: _formKey,
|
||||||
|
child: PageView(
|
||||||
|
physics: const NeverScrollableScrollPhysics(),
|
||||||
|
controller: _pageController,
|
||||||
|
children: <Widget>[
|
||||||
|
for (AuthStep step in widget.steps)
|
||||||
|
Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Flexible(
|
||||||
|
child: Center(
|
||||||
|
child: ListView(
|
||||||
|
physics: const ClampingScrollPhysics(),
|
||||||
|
shrinkWrap: true,
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
vertical: 8.0,
|
||||||
|
horizontal: 30.0,
|
||||||
|
),
|
||||||
|
children: [
|
||||||
|
for (AuthField field in step.fields)
|
||||||
|
Align(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(
|
||||||
|
top: 24.0,
|
||||||
|
bottom: 12.0,
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
field.title,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
field.build(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(
|
||||||
|
top: 15.0,
|
||||||
|
bottom: 30.0,
|
||||||
|
left: 30.0,
|
||||||
|
right: 30.0,
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: widget.steps.first != step
|
||||||
|
? MainAxisAlignment.spaceBetween
|
||||||
|
: MainAxisAlignment.end,
|
||||||
|
children: [
|
||||||
|
if (widget.steps.first != step)
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () => _pageController.previousPage(
|
||||||
duration: _animationDuration,
|
duration: _animationDuration,
|
||||||
curve: _animationCurve,
|
curve: _animationCurve,
|
||||||
),
|
),
|
||||||
);
|
child: Row(
|
||||||
}
|
children: [
|
||||||
|
const Icon(
|
||||||
/// Handles next button press.
|
Icons.arrow_back,
|
||||||
Future<void> onNext(AuthStep step) async {
|
size: 18,
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(left: 4.0),
|
||||||
|
child: Text(widget.previousBtnTitle),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () {
|
||||||
if (!_formKey.currentState!.validate()) {
|
if (!_formKey.currentState!.validate()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_formKey.currentState!.save();
|
|
||||||
|
|
||||||
FocusScope.of(context).unfocus();
|
FocusScope.of(context).unfocus();
|
||||||
|
|
||||||
if (widget.steps.last == step) {
|
if (widget.steps.last == step) {
|
||||||
var values = HashMap<String, dynamic>();
|
var values = HashMap<String, String>();
|
||||||
|
|
||||||
for (var step in widget.steps) {
|
for (var step in widget.steps) {
|
||||||
for (var field in step.fields) {
|
for (var field in step.fields) {
|
||||||
|
@ -184,238 +143,47 @@ class _AuthScreenState extends State<AuthScreen> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await widget.onFinish(
|
widget.onFinish(
|
||||||
values: values,
|
values: values,
|
||||||
onError: (int? pageToReturn) {
|
onError: () => _pageController.animateToPage(
|
||||||
if (pageToReturn == null) {
|
0,
|
||||||
return;
|
|
||||||
}
|
|
||||||
_pageController.animateToPage(
|
|
||||||
pageToReturn,
|
|
||||||
duration: _animationDuration,
|
duration: _animationDuration,
|
||||||
curve: _animationCurve,
|
curve: _animationCurve,
|
||||||
);
|
),
|
||||||
},
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
} else {
|
}
|
||||||
_validate(_pageController.page!.toInt() + 1);
|
|
||||||
unawaited(
|
|
||||||
_pageController.nextPage(
|
_pageController.nextPage(
|
||||||
duration: _animationDuration,
|
duration: _animationDuration,
|
||||||
curve: _animationCurve,
|
curve: _animationCurve,
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
},
|
||||||
}
|
|
||||||
|
|
||||||
/// Validates the current step.
|
|
||||||
void _validate(int currentPage) {
|
|
||||||
var isStepValid = true;
|
|
||||||
|
|
||||||
// Loop through each field in the current step
|
|
||||||
for (var field in widget.steps[currentPage].fields) {
|
|
||||||
for (var validator in field.validators) {
|
|
||||||
var validationResult = validator(field.value);
|
|
||||||
if (validationResult != null) {
|
|
||||||
// If any validator returns an error, mark step as invalid and break
|
|
||||||
isStepValid = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!isStepValid) {
|
|
||||||
break; // No need to check further fields if one is already invalid
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
setState(() {
|
|
||||||
_formValid = isStepValid;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
var theme = Theme.of(context);
|
|
||||||
return Scaffold(
|
|
||||||
backgroundColor: widget.customBackgroundColor ?? const Color(0xffFAF9F6),
|
|
||||||
appBar: _appBar,
|
|
||||||
body: SafeArea(
|
|
||||||
child: Form(
|
|
||||||
key: _formKey,
|
|
||||||
child: PageView(
|
|
||||||
physics: const NeverScrollableScrollPhysics(),
|
|
||||||
controller: _pageController,
|
|
||||||
children: <Widget>[
|
|
||||||
for (var currentStep = 0;
|
|
||||||
currentStep < widget.steps.length;
|
|
||||||
currentStep++)
|
|
||||||
Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
if (widget.titleWidget != null) ...[
|
|
||||||
Expanded(
|
|
||||||
flex: widget.titleFlex ?? 1,
|
|
||||||
child: Column(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
Expanded(
|
|
||||||
flex: widget.beforeTitleFlex ?? 2,
|
|
||||||
child: Container(),
|
|
||||||
),
|
|
||||||
widget.titleWidget!,
|
|
||||||
Expanded(
|
|
||||||
flex: widget.afterTitleFlex ?? 2,
|
|
||||||
child: Container(),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
Expanded(
|
|
||||||
flex: widget.formFlex ?? 3,
|
|
||||||
child: Align(
|
|
||||||
alignment: Alignment.topCenter,
|
|
||||||
child: ConstrainedBox(
|
|
||||||
constraints: BoxConstraints(
|
|
||||||
maxWidth: widget.maxFormWidth ?? 300,
|
|
||||||
),
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
for (AuthField field
|
|
||||||
in widget.steps[currentStep].fields) ...[
|
|
||||||
if (field.title != null) ...[
|
|
||||||
wrapWithDefaultStyle(
|
|
||||||
style: theme.textTheme.headlineLarge!,
|
|
||||||
widget: field.title!,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
field.build(context, () {
|
|
||||||
_validate(currentStep);
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Column(
|
|
||||||
children: [
|
|
||||||
SizedBox(
|
|
||||||
width: MediaQuery.of(context).size.width,
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(
|
|
||||||
horizontal: 20,
|
|
||||||
),
|
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment: widget.steps.first !=
|
|
||||||
widget.steps[currentStep]
|
|
||||||
? MainAxisAlignment.spaceBetween
|
|
||||||
: MainAxisAlignment.end,
|
|
||||||
children: [
|
children: [
|
||||||
if (widget.steps.first !=
|
Text(
|
||||||
widget.steps[currentStep]) ...[
|
widget.steps.last == step
|
||||||
widget.previousButtonBuilder?.call(
|
|
||||||
onPrevious,
|
|
||||||
widget.previousBtnTitle,
|
|
||||||
currentStep,
|
|
||||||
) ??
|
|
||||||
_stepButton(
|
|
||||||
buttonText: widget.previousBtnTitle,
|
|
||||||
onTap: () async => onPrevious(),
|
|
||||||
),
|
|
||||||
const SizedBox(
|
|
||||||
width: 8,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
widget.nextButtonBuilder?.call(
|
|
||||||
!_formValid
|
|
||||||
? null
|
|
||||||
: () async {
|
|
||||||
await onNext(
|
|
||||||
widget.steps[currentStep],
|
|
||||||
);
|
|
||||||
},
|
|
||||||
widget.steps.last ==
|
|
||||||
widget.steps[currentStep]
|
|
||||||
? widget.submitBtnTitle
|
? widget.submitBtnTitle
|
||||||
: widget.nextBtnTitle,
|
: widget.nextBtnTitle,
|
||||||
currentStep,
|
),
|
||||||
_formValid,
|
const Padding(
|
||||||
) ??
|
padding: EdgeInsets.only(left: 4.0),
|
||||||
_stepButton(
|
child: Icon(
|
||||||
buttonText: widget.steps.last ==
|
Icons.arrow_forward,
|
||||||
widget.steps[currentStep]
|
size: 18,
|
||||||
? widget.submitBtnTitle
|
),
|
||||||
: widget.nextBtnTitle,
|
|
||||||
onTap: () async {
|
|
||||||
await onNext(
|
|
||||||
widget.steps[currentStep],
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(
|
)
|
||||||
height: 8,
|
|
||||||
),
|
|
||||||
if (widget.loginButton != null)
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.only(top: 20.0),
|
|
||||||
child: widget.loginButton,
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
|
||||||
Widget _stepButton({
|
|
||||||
required String buttonText,
|
|
||||||
required Future Function()? onTap,
|
|
||||||
}) {
|
|
||||||
var theme = Theme.of(context);
|
|
||||||
return Flexible(
|
|
||||||
child: InkWell(
|
|
||||||
onTap: onTap,
|
|
||||||
child: Container(
|
|
||||||
width: double.infinity,
|
|
||||||
constraints: const BoxConstraints(
|
|
||||||
maxWidth: 180,
|
|
||||||
),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
borderRadius: BorderRadius.circular(20),
|
|
||||||
border: Border.all(
|
|
||||||
color: const Color(
|
|
||||||
0xff979797,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.all(4),
|
|
||||||
child: Text(
|
|
||||||
buttonText,
|
|
||||||
style: theme.textTheme.bodyMedium,
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget wrapWithDefaultStyle({
|
|
||||||
required Widget widget,
|
|
||||||
required TextStyle style,
|
|
||||||
}) =>
|
|
||||||
DefaultTextStyle(style: style, child: widget);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
import "dart:collection";
|
|
||||||
import "package:flutter/material.dart";
|
|
||||||
import "package:flutter_registration/flutter_registration.dart";
|
|
||||||
|
|
||||||
/// A registration repository that does nothing.
|
|
||||||
class ExampleRegistrationRepository with RegistrationRepository {
|
|
||||||
@override
|
|
||||||
Future<String?> register(HashMap values) {
|
|
||||||
debugPrint("register $values");
|
|
||||||
return Future.value(null);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -2,172 +2,35 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: BSD-3-Clause
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
import "dart:async";
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_registration/flutter_registration.dart';
|
||||||
|
|
||||||
import "package:flutter/material.dart";
|
|
||||||
import "package:flutter_registration/flutter_registration.dart";
|
|
||||||
import "package:flutter_registration/src/config/example_registration_repository.dart";
|
|
||||||
|
|
||||||
/// A set of options for configuring the
|
|
||||||
/// registration process in a Flutter application.
|
|
||||||
class RegistrationOptions {
|
class RegistrationOptions {
|
||||||
/// Registration options Constructor
|
|
||||||
RegistrationOptions({
|
RegistrationOptions({
|
||||||
|
required this.registrationRepository,
|
||||||
|
required this.registrationSteps,
|
||||||
required this.afterRegistration,
|
required this.afterRegistration,
|
||||||
this.registrationRepository,
|
this.registrationTranslations = const RegistrationTranslations(),
|
||||||
this.registrationSteps,
|
this.customAppbarBuilder,
|
||||||
this.titleFlex,
|
});
|
||||||
this.formFlex,
|
|
||||||
this.beforeTitleFlex,
|
|
||||||
this.afterTitleFlex,
|
|
||||||
this.registrationTranslations = const RegistrationTranslations.empty(),
|
|
||||||
this.onError,
|
|
||||||
this.customAppbarBuilder = _createCustomAppBar,
|
|
||||||
this.nextButtonBuilder,
|
|
||||||
this.previousButtonBuilder,
|
|
||||||
this.buttonMainAxisAlignment,
|
|
||||||
this.backgroundColor,
|
|
||||||
this.titleWidget,
|
|
||||||
this.loginButton,
|
|
||||||
this.maxFormWidth,
|
|
||||||
this.beforeRegistration,
|
|
||||||
}) {
|
|
||||||
if (registrationSteps == null || registrationSteps!.isEmpty) {
|
|
||||||
steps = RegistrationOptions.getDefaultSteps();
|
|
||||||
} else {
|
|
||||||
steps = registrationSteps!;
|
|
||||||
}
|
|
||||||
registrationRepository ??= ExampleRegistrationRepository();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Translations for registration-related messages and prompts.
|
|
||||||
final RegistrationTranslations registrationTranslations;
|
final RegistrationTranslations registrationTranslations;
|
||||||
|
final List<AuthStep> registrationSteps;
|
||||||
/// The steps involved in the registration process.
|
|
||||||
final List<AuthStep>? registrationSteps;
|
|
||||||
|
|
||||||
/// The steps involved in the registration process.
|
|
||||||
List<AuthStep> steps = [];
|
|
||||||
|
|
||||||
/// A function that handles errors during registration.
|
|
||||||
final int? Function(String error)? onError;
|
|
||||||
|
|
||||||
/// A callback function executed after successful registration.
|
|
||||||
final VoidCallback afterRegistration;
|
final VoidCallback afterRegistration;
|
||||||
|
final RegistrationRepository registrationRepository;
|
||||||
/// The repository responsible for registration.
|
|
||||||
RegistrationRepository? registrationRepository;
|
|
||||||
|
|
||||||
/// A function for customizing the app bar displayed during registration.
|
|
||||||
final AppBar Function(String title)? customAppbarBuilder;
|
final AppBar Function(String title)? customAppbarBuilder;
|
||||||
|
|
||||||
/// A function for customizing the "Next" button.
|
|
||||||
final Widget Function(
|
|
||||||
Future<void> Function()? onPressed,
|
|
||||||
String label,
|
|
||||||
int step,
|
|
||||||
// ignore: avoid_positional_boolean_parameters
|
|
||||||
bool enabled,
|
|
||||||
)? nextButtonBuilder;
|
|
||||||
|
|
||||||
/// A function for customizing the "Previous" button.
|
|
||||||
final Widget? Function(VoidCallback onPressed, String label, int step)?
|
|
||||||
previousButtonBuilder;
|
|
||||||
|
|
||||||
/// Specifies the alignment of buttons.
|
|
||||||
final MainAxisAlignment? buttonMainAxisAlignment;
|
|
||||||
|
|
||||||
/// The background color of the registration screen.
|
|
||||||
final Color? backgroundColor;
|
|
||||||
|
|
||||||
/// A custom widget for displaying the registration title.
|
|
||||||
final Widget? titleWidget;
|
|
||||||
|
|
||||||
/// A custom widget for displaying a login button.
|
|
||||||
final Widget? loginButton;
|
|
||||||
|
|
||||||
/// The number of flex units for the title.
|
|
||||||
final int? titleFlex;
|
|
||||||
|
|
||||||
/// The number of flex units for the form.
|
|
||||||
final int? formFlex;
|
|
||||||
|
|
||||||
/// The number of flex units for the buttons.
|
|
||||||
final int? beforeTitleFlex;
|
|
||||||
|
|
||||||
/// The number of flex units for the buttons.
|
|
||||||
final int? afterTitleFlex;
|
|
||||||
|
|
||||||
/// The maximum width of the form. Defaults to 300.
|
|
||||||
final double? maxFormWidth;
|
|
||||||
|
|
||||||
/// This function gets called before the user gets registered.
|
|
||||||
final Future<void> Function()? beforeRegistration;
|
|
||||||
|
|
||||||
/// Generates default registration steps.
|
|
||||||
///
|
|
||||||
/// [emailController] controller for email input.
|
|
||||||
///
|
|
||||||
/// [pass1Controller] controller for first password input.
|
|
||||||
///
|
|
||||||
/// [pass1Hidden] whether the first password field is initially hidden.
|
|
||||||
///
|
|
||||||
/// [pass2Controller] controller for second password input.
|
|
||||||
///
|
|
||||||
/// [pass2Hidden] whether the second password field is initially hidden.
|
|
||||||
///
|
|
||||||
/// [passHideOnChange] function triggered when password visibility changes.
|
|
||||||
///
|
|
||||||
/// [translations] translations for default registration messages and prompts.
|
|
||||||
///
|
|
||||||
/// [titleBuilder] function for customizing step titles.
|
|
||||||
///
|
|
||||||
/// [labelBuilder] function for customizing field labels.
|
|
||||||
///
|
|
||||||
/// [textStyle] text style for input fields.
|
|
||||||
///
|
|
||||||
/// [initialEmail] initial value for email input.
|
|
||||||
static List<AuthStep> getDefaultSteps({
|
static List<AuthStep> getDefaultSteps({
|
||||||
TextEditingController? emailController,
|
RegistrationTranslations translations = const RegistrationTranslations(),
|
||||||
TextEditingController? passController,
|
|
||||||
bool passHidden = true,
|
|
||||||
// ignore: avoid_positional_boolean_parameters
|
|
||||||
Function(bool mainPass, bool value)? passHideOnChange,
|
|
||||||
RegistrationTranslations translations =
|
|
||||||
const RegistrationTranslations.empty(),
|
|
||||||
Function(String title)? titleBuilder,
|
|
||||||
Function(String label)? labelBuilder,
|
|
||||||
TextStyle? textStyle,
|
|
||||||
TextStyle? hintStyle,
|
|
||||||
String? initialEmail,
|
|
||||||
}) =>
|
}) =>
|
||||||
[
|
[
|
||||||
AuthStep(
|
AuthStep(
|
||||||
fields: [
|
fields: [
|
||||||
AuthTextField(
|
AuthTextField(
|
||||||
name: "email",
|
name: 'email',
|
||||||
textEditingController: emailController,
|
title: translations.defaultEmailTitle,
|
||||||
value: initialEmail ?? "",
|
|
||||||
title: titleBuilder?.call(translations.defaultEmailTitle) ??
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.only(top: 180),
|
|
||||||
child: Text(
|
|
||||||
translations.defaultEmailTitle,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
textInputType: TextInputType.emailAddress,
|
|
||||||
textFieldDecoration: InputDecoration(
|
|
||||||
hintStyle: hintStyle,
|
|
||||||
contentPadding: const EdgeInsets.symmetric(horizontal: 8),
|
|
||||||
label: labelBuilder?.call(translations.defaultEmailLabel),
|
|
||||||
hintText: translations.defaultEmailHint,
|
hintText: translations.defaultEmailHint,
|
||||||
border: const OutlineInputBorder(),
|
|
||||||
focusedBorder: const OutlineInputBorder(),
|
|
||||||
),
|
|
||||||
textStyle: textStyle,
|
|
||||||
padding: const EdgeInsets.symmetric(vertical: 20),
|
|
||||||
validators: [
|
validators: [
|
||||||
// ignore: avoid_dynamic_calls
|
|
||||||
(email) => (email == null || email.isEmpty)
|
(email) => (email == null || email.isEmpty)
|
||||||
? translations.defaultEmailEmpty
|
? translations.defaultEmailEmpty
|
||||||
: null,
|
: null,
|
||||||
|
@ -177,52 +40,23 @@ class RegistrationOptions {
|
||||||
? null
|
? null
|
||||||
: translations.defaultEmailValidatorMessage,
|
: translations.defaultEmailValidatorMessage,
|
||||||
],
|
],
|
||||||
),
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
AuthStep(
|
AuthStep(
|
||||||
fields: [
|
fields: [
|
||||||
AuthPassField(
|
AuthTextField(
|
||||||
name: "password",
|
name: 'password',
|
||||||
textEditingController: passController,
|
title: translations.defaultPasswordTitle,
|
||||||
title: titleBuilder?.call(translations.defaultPasswordTitle) ??
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.only(top: 180),
|
|
||||||
child: Text(
|
|
||||||
translations.defaultPasswordTitle,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
textFieldDecoration: InputDecoration(
|
|
||||||
hintStyle: hintStyle,
|
|
||||||
contentPadding: const EdgeInsets.symmetric(horizontal: 8),
|
|
||||||
label: labelBuilder?.call(translations.defaultPasswordLabel),
|
|
||||||
hintText: translations.defaultPasswordHint,
|
hintText: translations.defaultPasswordHint,
|
||||||
border: const OutlineInputBorder(),
|
obscureText: true,
|
||||||
focusedBorder: const OutlineInputBorder(),
|
|
||||||
),
|
|
||||||
padding: const EdgeInsets.symmetric(vertical: 20),
|
|
||||||
textStyle: textStyle,
|
|
||||||
validators: [
|
validators: [
|
||||||
(value) {
|
(value) => (value == null || value.isEmpty)
|
||||||
// ignore: avoid_dynamic_calls
|
? translations.defaultPasswordValidatorMessage
|
||||||
if (value == null || value.isEmpty) {
|
: null,
|
||||||
return translations.defaultPasswordValidatorMessage;
|
|
||||||
}
|
|
||||||
// ignore: avoid_dynamic_calls
|
|
||||||
if (value.length < 6) {
|
|
||||||
return translations.defaultPasswordToShortValidatorMessage;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
AppBar _createCustomAppBar(String title) => AppBar(
|
|
||||||
iconTheme: const IconThemeData(color: Colors.black, size: 16),
|
|
||||||
title: Text(title),
|
|
||||||
backgroundColor: Colors.transparent,
|
|
||||||
);
|
|
||||||
|
|
|
@ -2,129 +2,32 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: BSD-3-Clause
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
/// Holds all the translations for the standard elements
|
|
||||||
/// on the registration screen.
|
|
||||||
class RegistrationTranslations {
|
class RegistrationTranslations {
|
||||||
/// Constructs a [RegistrationTranslations] object.
|
|
||||||
const RegistrationTranslations({
|
const RegistrationTranslations({
|
||||||
required this.title,
|
this.title = 'Registreren',
|
||||||
required this.registerBtn,
|
this.registerBtn = 'Registreren',
|
||||||
required this.previousStepBtn,
|
this.previousStepBtn = 'Vorige stap',
|
||||||
required this.nextStepBtn,
|
this.nextStepBtn = 'Volgende stap',
|
||||||
required this.closeBtn,
|
this.closeBtn = 'Sluiten',
|
||||||
required this.defaultEmailTitle,
|
this.defaultEmailTitle = 'Wat is je e-mailadres?',
|
||||||
required this.defaultEmailLabel,
|
this.defaultEmailHint = 'iemand@voorbeeld.nl',
|
||||||
required this.defaultEmailHint,
|
this.defaultEmailEmpty = 'Geef uw e-mailadres op',
|
||||||
required this.defaultEmailEmpty,
|
this.defaultEmailValidatorMessage = 'Geef een geldig e-mailadres op',
|
||||||
required this.defaultEmailValidatorMessage,
|
this.defaultPasswordTitle = 'Kies een wachtwoord',
|
||||||
required this.defaultPasswordTitle,
|
this.defaultPasswordHint = '',
|
||||||
required this.defaultPasswordLabel,
|
this.defaultPasswordValidatorMessage = 'Geef een wachtwoord op',
|
||||||
required this.defaultPasswordHint,
|
|
||||||
required this.defaultPasswordValidatorMessage,
|
|
||||||
required this.defaultPasswordToShortValidatorMessage,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
/// Constructs a [RegistrationTranslations] object with empty strings.
|
|
||||||
const RegistrationTranslations.empty()
|
|
||||||
: title = "",
|
|
||||||
registerBtn = "Register",
|
|
||||||
previousStepBtn = "Previous",
|
|
||||||
nextStepBtn = "Next",
|
|
||||||
closeBtn = "Close",
|
|
||||||
defaultEmailTitle = "enter your email address",
|
|
||||||
defaultEmailLabel = "",
|
|
||||||
defaultEmailHint = "Email address",
|
|
||||||
defaultEmailEmpty = "Please enter your email address.",
|
|
||||||
defaultEmailValidatorMessage = "Please enter a valid email address.",
|
|
||||||
defaultPasswordTitle = "choose a password",
|
|
||||||
defaultPasswordLabel = "",
|
|
||||||
defaultPasswordHint = "Password",
|
|
||||||
defaultPasswordValidatorMessage = "Enter a valid password",
|
|
||||||
defaultPasswordToShortValidatorMessage =
|
|
||||||
"Password needs to be at least 6 characters long";
|
|
||||||
|
|
||||||
/// The title of the registration screen.
|
|
||||||
final String title;
|
final String title;
|
||||||
|
|
||||||
/// The text for the registration button.
|
|
||||||
final String registerBtn;
|
final String registerBtn;
|
||||||
|
|
||||||
/// The text for the previous step button.
|
|
||||||
final String previousStepBtn;
|
final String previousStepBtn;
|
||||||
|
|
||||||
/// The text for the next step button.
|
|
||||||
final String nextStepBtn;
|
final String nextStepBtn;
|
||||||
|
|
||||||
/// The text for the close button.
|
|
||||||
final String closeBtn;
|
final String closeBtn;
|
||||||
|
|
||||||
/// The title for the default email field.
|
|
||||||
final String defaultEmailTitle;
|
final String defaultEmailTitle;
|
||||||
|
|
||||||
/// The label for the default email field.
|
|
||||||
final String defaultEmailLabel;
|
|
||||||
|
|
||||||
/// The hint for the default email field.
|
|
||||||
final String defaultEmailHint;
|
final String defaultEmailHint;
|
||||||
|
|
||||||
/// The message for an empty default email field.
|
|
||||||
final String defaultEmailEmpty;
|
final String defaultEmailEmpty;
|
||||||
|
|
||||||
/// The message for an invalid default email field.
|
|
||||||
final String defaultEmailValidatorMessage;
|
final String defaultEmailValidatorMessage;
|
||||||
|
|
||||||
/// The title for the default password field.
|
|
||||||
final String defaultPasswordTitle;
|
final String defaultPasswordTitle;
|
||||||
|
|
||||||
/// The label for the default password field.
|
|
||||||
final String defaultPasswordLabel;
|
|
||||||
|
|
||||||
/// The hint for the default password field.
|
|
||||||
final String defaultPasswordHint;
|
final String defaultPasswordHint;
|
||||||
|
|
||||||
/// The message for an invalid default password field.
|
|
||||||
final String defaultPasswordValidatorMessage;
|
final String defaultPasswordValidatorMessage;
|
||||||
|
|
||||||
/// The message for a default password that is too short.
|
|
||||||
final String defaultPasswordToShortValidatorMessage;
|
|
||||||
|
|
||||||
/// create a copywith
|
|
||||||
RegistrationTranslations copyWith({
|
|
||||||
String? title,
|
|
||||||
String? registerBtn,
|
|
||||||
String? previousStepBtn,
|
|
||||||
String? nextStepBtn,
|
|
||||||
String? closeBtn,
|
|
||||||
String? defaultEmailTitle,
|
|
||||||
String? defaultEmailLabel,
|
|
||||||
String? defaultEmailHint,
|
|
||||||
String? defaultEmailEmpty,
|
|
||||||
String? defaultEmailValidatorMessage,
|
|
||||||
String? defaultPasswordTitle,
|
|
||||||
String? defaultPasswordLabel,
|
|
||||||
String? defaultPasswordHint,
|
|
||||||
String? defaultPasswordValidatorMessage,
|
|
||||||
String? defaultPasswordToShortValidatorMessage,
|
|
||||||
}) =>
|
|
||||||
RegistrationTranslations(
|
|
||||||
title: title ?? this.title,
|
|
||||||
registerBtn: registerBtn ?? this.registerBtn,
|
|
||||||
previousStepBtn: previousStepBtn ?? this.previousStepBtn,
|
|
||||||
nextStepBtn: nextStepBtn ?? this.nextStepBtn,
|
|
||||||
closeBtn: closeBtn ?? this.closeBtn,
|
|
||||||
defaultEmailTitle: defaultEmailTitle ?? this.defaultEmailTitle,
|
|
||||||
defaultEmailLabel: defaultEmailLabel ?? this.defaultEmailLabel,
|
|
||||||
defaultEmailHint: defaultEmailHint ?? this.defaultEmailHint,
|
|
||||||
defaultEmailEmpty: defaultEmailEmpty ?? this.defaultEmailEmpty,
|
|
||||||
defaultEmailValidatorMessage:
|
|
||||||
defaultEmailValidatorMessage ?? this.defaultEmailValidatorMessage,
|
|
||||||
defaultPasswordTitle: defaultPasswordTitle ?? this.defaultPasswordTitle,
|
|
||||||
defaultPasswordLabel: defaultPasswordLabel ?? this.defaultPasswordLabel,
|
|
||||||
defaultPasswordHint: defaultPasswordHint ?? this.defaultPasswordHint,
|
|
||||||
defaultPasswordValidatorMessage: defaultPasswordValidatorMessage ??
|
|
||||||
this.defaultPasswordValidatorMessage,
|
|
||||||
defaultPasswordToShortValidatorMessage:
|
|
||||||
defaultPasswordToShortValidatorMessage ??
|
|
||||||
this.defaultPasswordToShortValidatorMessage,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,19 +2,14 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: BSD-3-Clause
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
import "package:flutter/material.dart";
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
/// An action that can be performed during authentication.
|
|
||||||
class AuthAction {
|
class AuthAction {
|
||||||
/// Constructs an [AuthAction] object.
|
|
||||||
AuthAction({
|
AuthAction({
|
||||||
required this.title,
|
required this.title,
|
||||||
required this.onPress,
|
required this.onPress,
|
||||||
});
|
});
|
||||||
|
|
||||||
/// The title of the action.
|
|
||||||
final String title;
|
final String title;
|
||||||
|
|
||||||
/// A callback function triggered when the action is pressed.
|
|
||||||
final VoidCallback onPress;
|
final VoidCallback onPress;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,78 +0,0 @@
|
||||||
// SPDX-FileCopyrightText: 2022 Iconica
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: BSD-3-Clause
|
|
||||||
|
|
||||||
import "package:flutter/material.dart";
|
|
||||||
import "package:flutter_input_library/flutter_input_library.dart";
|
|
||||||
import "package:flutter_registration/flutter_registration.dart";
|
|
||||||
|
|
||||||
/// A field for capturing boolean values in a Flutter form.
|
|
||||||
///
|
|
||||||
/// Extends [AuthField].
|
|
||||||
class AuthBoolField extends AuthField {
|
|
||||||
/// Constructs an [AuthBoolField] object.
|
|
||||||
///
|
|
||||||
/// [name] specifies the name of the field.
|
|
||||||
///
|
|
||||||
/// [widgetType] defines the type of boolean widget to use.
|
|
||||||
///
|
|
||||||
/// [title] specifies the title of the field (optional).
|
|
||||||
///
|
|
||||||
/// [validators] defines a list of validation functions for the field.
|
|
||||||
///
|
|
||||||
/// [value] specifies the initial value of the field (default is false).
|
|
||||||
///
|
|
||||||
/// [leftWidget] is a widget to be displayed on the
|
|
||||||
/// left side of the boolean widget.
|
|
||||||
///
|
|
||||||
/// [rightWidget] is a widget to be displayed on the
|
|
||||||
/// right side of the boolean widget.
|
|
||||||
///
|
|
||||||
/// [onChange] is a callback function triggered when
|
|
||||||
/// the value of the field changes.
|
|
||||||
AuthBoolField({
|
|
||||||
required super.name,
|
|
||||||
required this.widgetType,
|
|
||||||
super.title,
|
|
||||||
super.validators = const [],
|
|
||||||
super.value = false,
|
|
||||||
this.leftWidget,
|
|
||||||
this.rightWidget,
|
|
||||||
this.onChange,
|
|
||||||
});
|
|
||||||
|
|
||||||
/// A widget to be displayed on the left side of the boolean widget.
|
|
||||||
final Widget? leftWidget;
|
|
||||||
|
|
||||||
/// A widget to be displayed on the right side of the boolean widget.
|
|
||||||
final Widget? rightWidget;
|
|
||||||
|
|
||||||
/// The type of boolean widget to use.
|
|
||||||
final BoolWidgetType widgetType;
|
|
||||||
|
|
||||||
/// A callback function triggered when the value of the field changes.
|
|
||||||
final Function(String value)? onChange;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context, Function onValueChanged) =>
|
|
||||||
FlutterFormInputBool(
|
|
||||||
widgetType: widgetType,
|
|
||||||
onChanged: (v) {
|
|
||||||
value = v;
|
|
||||||
onChange?.call(value);
|
|
||||||
// ignore: avoid_dynamic_calls
|
|
||||||
onValueChanged();
|
|
||||||
},
|
|
||||||
validator: (value) {
|
|
||||||
for (var validator in validators) {
|
|
||||||
var output = validator(value);
|
|
||||||
if (output != null) {
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
leftWidget: leftWidget,
|
|
||||||
rightWidget: rightWidget,
|
|
||||||
);
|
|
||||||
}
|
|
|
@ -1,78 +0,0 @@
|
||||||
import "package:flutter/material.dart";
|
|
||||||
import "package:flutter_registration/flutter_registration.dart";
|
|
||||||
|
|
||||||
/// A field for capturing dropdown selections in a Flutter form.
|
|
||||||
///
|
|
||||||
/// Extends [AuthField].
|
|
||||||
class AuthDropdownField extends AuthField {
|
|
||||||
/// Constructs an [AuthDropdownField] object.
|
|
||||||
AuthDropdownField({
|
|
||||||
required super.name,
|
|
||||||
required this.items,
|
|
||||||
required this.onChanged,
|
|
||||||
required super.value,
|
|
||||||
this.dropdownDecoration,
|
|
||||||
this.padding = const EdgeInsets.all(8.0),
|
|
||||||
this.textStyle,
|
|
||||||
this.icon = const Icon(Icons.keyboard_arrow_down),
|
|
||||||
}) {
|
|
||||||
selectedValue = value ?? items.first;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The list of items for the dropdown.
|
|
||||||
final List<String> items;
|
|
||||||
|
|
||||||
/// A callback function triggered when the dropdown value changes.
|
|
||||||
final Function(String?) onChanged;
|
|
||||||
|
|
||||||
/// The currently selected value in the dropdown.
|
|
||||||
String? selectedValue;
|
|
||||||
|
|
||||||
/// The decoration for the dropdown.
|
|
||||||
final InputDecoration? dropdownDecoration;
|
|
||||||
|
|
||||||
/// The padding around the dropdown.
|
|
||||||
final EdgeInsets padding;
|
|
||||||
|
|
||||||
/// The text style for the dropdown.
|
|
||||||
final TextStyle? textStyle;
|
|
||||||
|
|
||||||
/// The icon to be displayed with the dropdown.
|
|
||||||
final Icon icon;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context, Function onValueChanged) => Padding(
|
|
||||||
padding: padding,
|
|
||||||
child: DropdownButtonFormField<String>(
|
|
||||||
icon: icon,
|
|
||||||
style: textStyle,
|
|
||||||
value: selectedValue,
|
|
||||||
decoration: dropdownDecoration,
|
|
||||||
items: items
|
|
||||||
.map(
|
|
||||||
(String value) => DropdownMenuItem<String>(
|
|
||||||
value: value,
|
|
||||||
child: Text(value),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.toList(),
|
|
||||||
onChanged: (newValue) {
|
|
||||||
selectedValue = newValue;
|
|
||||||
onChanged(newValue);
|
|
||||||
// ignore: avoid_dynamic_calls
|
|
||||||
onValueChanged();
|
|
||||||
},
|
|
||||||
validator: (value) {
|
|
||||||
if (validators.isNotEmpty) {
|
|
||||||
for (var validator in validators) {
|
|
||||||
var output = validator(value);
|
|
||||||
if (output != null) {
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
|
@ -2,14 +2,12 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: BSD-3-Clause
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
/// An exception thrown when an authentication error occurs.
|
|
||||||
class AuthException implements Exception {
|
class AuthException implements Exception {
|
||||||
/// Constructs an [AuthException] object.
|
|
||||||
AuthException(this.message);
|
AuthException(this.message);
|
||||||
|
|
||||||
/// The error message.
|
|
||||||
final String message;
|
final String message;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() => message;
|
String toString() {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,53 +2,20 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: BSD-3-Clause
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
import "package:flutter/material.dart";
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
/// An abstract class representing a field in a Flutter form.
|
abstract class AuthField {
|
||||||
///
|
|
||||||
/// [T] represents the type of value stored in the field.
|
|
||||||
abstract class AuthField<T> {
|
|
||||||
/// Constructs an [AuthField] object.
|
|
||||||
///
|
|
||||||
/// [name] specifies the name of the field.
|
|
||||||
///
|
|
||||||
/// [value] specifies the initial value of the field.
|
|
||||||
///
|
|
||||||
/// [onValueChanged] is a callback function triggered when the
|
|
||||||
/// value of the field changes (optional).
|
|
||||||
///
|
|
||||||
/// [title] specifies the title widget of the field (optional).
|
|
||||||
///
|
|
||||||
/// [validators] defines a list of validation
|
|
||||||
/// functions for the field (optional).
|
|
||||||
AuthField({
|
AuthField({
|
||||||
required this.name,
|
required this.name,
|
||||||
required this.value,
|
required this.title,
|
||||||
this.onValueChanged,
|
|
||||||
this.title,
|
|
||||||
this.validators = const [],
|
this.validators = const [],
|
||||||
|
this.value = '',
|
||||||
});
|
});
|
||||||
|
|
||||||
/// The name of the field.
|
|
||||||
final String name;
|
final String name;
|
||||||
|
final String title;
|
||||||
|
List<String? Function(String?)> validators;
|
||||||
|
String value;
|
||||||
|
|
||||||
/// The initial value of the field.
|
Widget build();
|
||||||
T value;
|
|
||||||
|
|
||||||
/// A callback function triggered when the value of the field changes.
|
|
||||||
final Function(T)? onValueChanged;
|
|
||||||
|
|
||||||
/// The title widget of the field.
|
|
||||||
final Widget? title;
|
|
||||||
|
|
||||||
/// A list of validation functions for the field.
|
|
||||||
List<String? Function(T?)> validators;
|
|
||||||
|
|
||||||
/// Builds the widget representing the field.
|
|
||||||
///
|
|
||||||
/// [context] The build context.
|
|
||||||
///
|
|
||||||
/// [onValueChanged] A function to be called when
|
|
||||||
/// the value of the field changes.
|
|
||||||
Widget build(BuildContext context, Function onValueChanged);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,96 +0,0 @@
|
||||||
// SPDX-FileCopyrightText: 2024 Iconica
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: BSD-3-Clause
|
|
||||||
|
|
||||||
import "package:flutter/material.dart";
|
|
||||||
import "package:flutter_input_library/flutter_input_library.dart";
|
|
||||||
import "package:flutter_registration/flutter_registration.dart";
|
|
||||||
|
|
||||||
/// A field for capturing password inputs in a Flutter form.
|
|
||||||
///
|
|
||||||
/// Extends [AuthField].
|
|
||||||
class AuthPassField extends AuthField {
|
|
||||||
/// Constructs an [AuthPassField] object.
|
|
||||||
///
|
|
||||||
/// [name] specifies the name of the field.
|
|
||||||
///
|
|
||||||
/// [textEditingController] controller for the password input (optional).
|
|
||||||
///
|
|
||||||
/// [title] specifies the title widget of the field (optional).
|
|
||||||
///
|
|
||||||
/// [validators] defines a list of validation
|
|
||||||
/// functions for the field (optional).
|
|
||||||
///
|
|
||||||
/// [value] specifies the initial value of the
|
|
||||||
/// field (default is an empty string).
|
|
||||||
///
|
|
||||||
/// [textStyle] defines the text style for the password input.
|
|
||||||
///
|
|
||||||
/// [onChange] is a callback function triggered when
|
|
||||||
/// the value of the field changes.
|
|
||||||
///
|
|
||||||
/// [iconSize] specifies the size of the icon displayed
|
|
||||||
/// with the password input (optional).
|
|
||||||
///
|
|
||||||
/// [textFieldDecoration] defines the decoration for the
|
|
||||||
/// password input field (optional).
|
|
||||||
///
|
|
||||||
/// [padding] defines the padding around the password input
|
|
||||||
/// field (default is EdgeInsets.all(8.0)).
|
|
||||||
AuthPassField({
|
|
||||||
required super.name,
|
|
||||||
this.textEditingController,
|
|
||||||
super.title,
|
|
||||||
super.validators = const [],
|
|
||||||
super.value = "",
|
|
||||||
this.textStyle,
|
|
||||||
this.onChange,
|
|
||||||
this.iconSize,
|
|
||||||
this.textFieldDecoration,
|
|
||||||
this.padding = const EdgeInsets.all(8.0),
|
|
||||||
});
|
|
||||||
|
|
||||||
/// The text style for the password input.
|
|
||||||
final TextStyle? textStyle;
|
|
||||||
|
|
||||||
/// The size of the icon displayed with the password input.
|
|
||||||
final double? iconSize;
|
|
||||||
|
|
||||||
/// A callback function triggered when the value of the field changes.
|
|
||||||
final Function(String value)? onChange;
|
|
||||||
|
|
||||||
/// The decoration for the password input field.
|
|
||||||
final InputDecoration? textFieldDecoration;
|
|
||||||
|
|
||||||
/// The padding around the password input field.
|
|
||||||
final EdgeInsets padding;
|
|
||||||
|
|
||||||
/// The controller for the password input.
|
|
||||||
final TextEditingController? textEditingController;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context, Function onValueChanged) => Padding(
|
|
||||||
padding: padding,
|
|
||||||
child: FlutterFormInputPassword(
|
|
||||||
style: textStyle,
|
|
||||||
iconSize: iconSize ?? 24.0,
|
|
||||||
decoration: textFieldDecoration,
|
|
||||||
onChanged: (v) {
|
|
||||||
value = v;
|
|
||||||
onChange?.call(value);
|
|
||||||
// ignore: avoid_dynamic_calls
|
|
||||||
onValueChanged();
|
|
||||||
},
|
|
||||||
validator: (value) {
|
|
||||||
for (var validator in validators) {
|
|
||||||
var output = validator(value);
|
|
||||||
if (output != null) {
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
|
@ -2,15 +2,12 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: BSD-3-Clause
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
import "package:flutter_registration/src/model/auth_field.dart";
|
import 'package:flutter_registration/src/model/auth_field.dart';
|
||||||
|
|
||||||
/// A step in the authentication process.
|
|
||||||
class AuthStep {
|
class AuthStep {
|
||||||
/// Constructs an [AuthStep] object.
|
|
||||||
AuthStep({
|
AuthStep({
|
||||||
required this.fields,
|
required this.fields,
|
||||||
});
|
});
|
||||||
|
|
||||||
/// The fields in the step.
|
|
||||||
List<AuthField> fields;
|
List<AuthField> fields;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,84 +2,34 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: BSD-3-Clause
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
import "package:flutter/material.dart";
|
import 'package:flutter/material.dart';
|
||||||
import "package:flutter_registration/flutter_registration.dart";
|
import 'package:flutter_registration/flutter_registration.dart';
|
||||||
|
|
||||||
/// A field for capturing text inputs in a Flutter form.
|
|
||||||
///
|
|
||||||
/// Extends [AuthField].
|
|
||||||
class AuthTextField extends AuthField {
|
class AuthTextField extends AuthField {
|
||||||
/// Constructs an [AuthTextField] object.
|
|
||||||
///
|
|
||||||
/// [name] specifies the name of the field.
|
|
||||||
///
|
|
||||||
/// [textEditingController] controller for the text input (optional).
|
|
||||||
///
|
|
||||||
/// [title] specifies the title widget of the field (optional).
|
|
||||||
///
|
|
||||||
/// [validators] defines a list of validation
|
|
||||||
/// functions for the field (optional).
|
|
||||||
///
|
|
||||||
/// [value] specifies the initial value of the
|
|
||||||
/// field (default is an empty string).
|
|
||||||
///
|
|
||||||
/// [textStyle] defines the text style for the text input.
|
|
||||||
///
|
|
||||||
/// [onChange] is a callback function triggered
|
|
||||||
/// when the value of the field changes.
|
|
||||||
///
|
|
||||||
/// [textFieldDecoration] defines the decoration
|
|
||||||
/// for the text input field (optional).
|
|
||||||
///
|
|
||||||
/// [padding] defines the padding around the text
|
|
||||||
/// input field (default is EdgeInsets.all(8.0)).
|
|
||||||
AuthTextField({
|
AuthTextField({
|
||||||
required super.name,
|
required super.name,
|
||||||
TextEditingController? textEditingController,
|
required super.title,
|
||||||
super.title,
|
|
||||||
super.validators = const [],
|
super.validators = const [],
|
||||||
super.value = "",
|
super.value = '',
|
||||||
this.textStyle,
|
this.obscureText = false,
|
||||||
this.onChange,
|
this.hintText,
|
||||||
this.textFieldDecoration,
|
|
||||||
this.padding = const EdgeInsets.all(8.0),
|
|
||||||
this.textInputType,
|
|
||||||
}) {
|
}) {
|
||||||
textController =
|
_textEditingController = TextEditingController();
|
||||||
textEditingController ?? TextEditingController(text: value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The controller for the text input.
|
late TextEditingController _textEditingController;
|
||||||
late TextEditingController textController;
|
final bool obscureText;
|
||||||
|
final String? hintText;
|
||||||
/// The text style for the text input.
|
|
||||||
final TextStyle? textStyle;
|
|
||||||
|
|
||||||
/// A callback function triggered when the value of the field changes.
|
|
||||||
final Function(String value)? onChange;
|
|
||||||
|
|
||||||
/// The decoration for the text input field.
|
|
||||||
final InputDecoration? textFieldDecoration;
|
|
||||||
|
|
||||||
/// The padding around the text input field.
|
|
||||||
final EdgeInsets padding;
|
|
||||||
|
|
||||||
/// The type of text input.
|
|
||||||
final TextInputType? textInputType;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, Function onValueChanged) => Padding(
|
Widget build() => TextFormField(
|
||||||
padding: padding,
|
decoration: InputDecoration(
|
||||||
child: TextFormField(
|
hintText: hintText,
|
||||||
keyboardType: textInputType,
|
),
|
||||||
style: textStyle,
|
controller: _textEditingController,
|
||||||
decoration: textFieldDecoration,
|
obscureText: obscureText,
|
||||||
controller: textController,
|
|
||||||
onChanged: (v) {
|
onChanged: (v) {
|
||||||
value = v;
|
value = v;
|
||||||
onChange?.call(value);
|
|
||||||
// ignore: avoid_dynamic_calls
|
|
||||||
onValueChanged();
|
|
||||||
},
|
},
|
||||||
validator: (value) {
|
validator: (value) {
|
||||||
for (var validator in validators) {
|
for (var validator in validators) {
|
||||||
|
@ -91,6 +41,5 @@ class AuthTextField extends AuthField {
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,77 +1,49 @@
|
||||||
import "dart:collection";
|
// SPDX-FileCopyrightText: 2022 Iconica
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
import "package:flutter/material.dart";
|
import 'dart:collection';
|
||||||
import "package:flutter_registration/flutter_registration.dart";
|
|
||||||
import "package:flutter_registration/src/auth_screen.dart";
|
|
||||||
|
|
||||||
/// A screen for user registration.
|
import 'package:flutter/material.dart';
|
||||||
class RegistrationScreen extends StatefulWidget {
|
import 'package:flutter_registration/flutter_registration.dart';
|
||||||
/// Constructs a [RegistrationScreen] object.
|
import 'package:flutter_registration/src/auth_screen.dart';
|
||||||
///
|
|
||||||
/// [registrationOptions] specifies the registration options.
|
class RegistrationScreen extends StatelessWidget {
|
||||||
const RegistrationScreen({
|
const RegistrationScreen({
|
||||||
required this.registrationOptions,
|
required this.registrationOptions,
|
||||||
super.key,
|
super.key,
|
||||||
});
|
});
|
||||||
|
|
||||||
/// The registration options.
|
|
||||||
final RegistrationOptions registrationOptions;
|
final RegistrationOptions registrationOptions;
|
||||||
|
|
||||||
@override
|
|
||||||
RegistrationScreenState createState() => RegistrationScreenState();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The state for [RegistrationScreen].
|
|
||||||
class RegistrationScreenState extends State<RegistrationScreen> {
|
|
||||||
/// Registers the user.
|
|
||||||
Future<void> _register({
|
|
||||||
required HashMap<String, dynamic> values,
|
|
||||||
required void Function(int? pageToReturn) onError,
|
|
||||||
}) async {
|
|
||||||
try {
|
|
||||||
await widget.registrationOptions.beforeRegistration?.call();
|
|
||||||
|
|
||||||
var registered = await widget.registrationOptions.registrationRepository!
|
|
||||||
.register(values);
|
|
||||||
|
|
||||||
if (registered == null) {
|
|
||||||
widget.registrationOptions.afterRegistration();
|
|
||||||
} else {
|
|
||||||
var pageToReturn = widget.registrationOptions.onError?.call(registered);
|
|
||||||
|
|
||||||
onError(pageToReturn);
|
|
||||||
}
|
|
||||||
} on Exception catch (_) {
|
|
||||||
onError(null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
var translations = widget.registrationOptions.registrationTranslations;
|
var translations = registrationOptions.registrationTranslations;
|
||||||
|
|
||||||
|
void register({
|
||||||
|
required HashMap<String, String> values,
|
||||||
|
required VoidCallback onError,
|
||||||
|
}) =>
|
||||||
|
registrationOptions.registrationRepository.register(values).then(
|
||||||
|
(response) {
|
||||||
|
if (response) {
|
||||||
|
registrationOptions.afterRegistration();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
).catchError((_) {
|
||||||
|
onError();
|
||||||
|
});
|
||||||
|
|
||||||
return AuthScreen(
|
return AuthScreen(
|
||||||
steps: widget.registrationOptions.steps,
|
steps: registrationOptions.registrationSteps,
|
||||||
customAppBar: widget.registrationOptions.customAppbarBuilder?.call(
|
customAppBar: registrationOptions.customAppbarBuilder?.call(
|
||||||
translations.title,
|
translations.title,
|
||||||
),
|
),
|
||||||
onFinish: _register,
|
onFinish: register,
|
||||||
appBarTitle: translations.title,
|
title: translations.title,
|
||||||
submitBtnTitle: translations.registerBtn,
|
submitBtnTitle: translations.registerBtn,
|
||||||
nextBtnTitle: translations.nextStepBtn,
|
nextBtnTitle: translations.nextStepBtn,
|
||||||
previousBtnTitle: translations.previousStepBtn,
|
previousBtnTitle: translations.previousStepBtn,
|
||||||
nextButtonBuilder: widget.registrationOptions.nextButtonBuilder,
|
|
||||||
previousButtonBuilder: widget.registrationOptions.previousButtonBuilder,
|
|
||||||
buttonMainAxisAlignment:
|
|
||||||
widget.registrationOptions.buttonMainAxisAlignment,
|
|
||||||
customBackgroundColor: widget.registrationOptions.backgroundColor,
|
|
||||||
titleWidget: widget.registrationOptions.titleWidget,
|
|
||||||
loginButton: widget.registrationOptions.loginButton,
|
|
||||||
titleFlex: widget.registrationOptions.titleFlex,
|
|
||||||
formFlex: widget.registrationOptions.formFlex,
|
|
||||||
beforeTitleFlex: widget.registrationOptions.beforeTitleFlex,
|
|
||||||
afterTitleFlex: widget.registrationOptions.afterTitleFlex,
|
|
||||||
maxFormWidth: widget.registrationOptions.maxFormWidth,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,10 +2,8 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: BSD-3-Clause
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
import "dart:collection";
|
import 'dart:collection';
|
||||||
|
|
||||||
/// A mixin for a registration repository.
|
|
||||||
mixin RegistrationRepository {
|
mixin RegistrationRepository {
|
||||||
/// Registers a user with the given values.
|
Future<bool> register(HashMap values);
|
||||||
Future<String?> register(HashMap values);
|
|
||||||
}
|
}
|
||||||
|
|
16
pubspec.yaml
16
pubspec.yaml
|
@ -4,31 +4,23 @@
|
||||||
|
|
||||||
name: flutter_registration
|
name: flutter_registration
|
||||||
description: A Flutter Registration package
|
description: A Flutter Registration package
|
||||||
version: 3.0.0
|
version: 0.1.0
|
||||||
repository: https://github.com/Iconica-Development/flutter_registration
|
repository: https://github.com/Iconica-Development/flutter_registration
|
||||||
|
|
||||||
publish_to: https://forgejo.internal.iconica.nl/api/packages/internal/pub
|
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=3.0.0 <4.0.0"
|
sdk: '>=2.18.0 <3.0.0'
|
||||||
flutter: ">=1.17.0"
|
flutter: ">=1.17.0"
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
flutter_input_library:
|
|
||||||
hosted: https://forgejo.internal.iconica.nl/api/packages/internal/pub
|
|
||||||
version: ^3.6.0
|
|
||||||
|
|
||||||
flutter:
|
flutter:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
flutter_localizations:
|
flutter_localizations:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
|
flutter_hooks: any
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
flutter_iconica_analysis:
|
flutter_lints: ^2.0.0
|
||||||
git:
|
|
||||||
url: https://github.com/Iconica-Development/flutter_iconica_analysis
|
|
||||||
ref: 7.0.0
|
|
||||||
|
|
||||||
flutter:
|
flutter:
|
|
@ -3,10 +3,10 @@
|
||||||
// SPDX-License-Identifier: BSD-3-Clause
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
import "package:flutter_test/flutter_test.dart";
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
test("test", () {
|
test('test', () {
|
||||||
expect(true, true);
|
expect(true, true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue