Merge pull request #20 from Iconica-Development/doc/improve-documentation

refactor: add documentation to files
This commit is contained in:
Gorter-dev 2024-04-03 14:56:58 +02:00 committed by GitHub
commit 7890c17587
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 341 additions and 160 deletions

View file

@ -7,7 +7,45 @@ import 'dart:collection';
import 'package:flutter/material.dart';
import 'package:flutter_registration/flutter_registration.dart';
/// A widget for handling multi-step authentication processes.
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.
///
/// [isLoading] indicates whether the screen is in a loading state.
const AuthScreen({
required this.appBarTitle,
required this.steps,
@ -27,8 +65,9 @@ class AuthScreen extends StatefulWidget {
this.beforeTitleFlex,
this.afterTitleFlex,
this.isLoading = false,
super.key,
}) : assert(steps.length > 0, 'At least one step is required');
Key? key,
}) : assert(steps.length > 0, 'At least one step is required'),
super(key: key);
final String appBarTitle;
final Future<void> Function({
@ -58,6 +97,7 @@ class AuthScreen extends StatefulWidget {
State<AuthScreen> createState() => _AuthScreenState();
}
/// The state for [AuthScreen].
class _AuthScreenState extends State<AuthScreen> {
final _formKey = GlobalKey<FormState>();
final _pageController = PageController();
@ -65,12 +105,14 @@ class _AuthScreenState extends State<AuthScreen> {
final _animationCurve = Curves.ease;
bool _formValid = false;
/// Gets the app bar.
AppBar get _appBar =>
widget.customAppBar ??
AppBar(
title: Text(widget.appBarTitle),
);
/// Handles previous button press.
void onPrevious() {
FocusScope.of(context).unfocus();
_validate(_pageController.page!.toInt() - 1);
@ -80,6 +122,7 @@ class _AuthScreenState extends State<AuthScreen> {
);
}
/// Handles next button press.
Future<void> onNext(AuthStep step) async {
if (!_formKey.currentState!.validate()) {
return;
@ -117,6 +160,7 @@ class _AuthScreenState extends State<AuthScreen> {
}
}
/// Validates the current step.
void _validate(int currentPage) {
bool isStepValid = true;
@ -156,137 +200,131 @@ class _AuthScreenState extends State<AuthScreen> {
body: Form(
key: _formKey,
child: PageView(
physics: const NeverScrollableScrollPhysics(),
controller: _pageController,
children: <Widget>[
for (var i = 0; i < widget.steps.length; i++)
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 ?? 3,
child: Container(),
),
widget.titleWidget!,
Expanded(
flex: widget.afterTitleFlex ?? 2,
child: Container(),
),
],
physics: const NeverScrollableScrollPhysics(),
controller: _pageController,
children: <Widget>[
for (var i = 0; i < widget.steps.length; i++)
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 ?? 3,
child: Container(),
),
),
Column(
widget.titleWidget!,
Expanded(
flex: widget.afterTitleFlex ?? 2,
child: Container(),
),
],
),
),
Column(
children: [
Row(
mainAxisAlignment: widget
.buttonMainAxisAlignment !=
null
? widget.buttonMainAxisAlignment!
: (widget.previousButtonBuilder != null &&
widget.previousButtonBuilder?.call(
onPrevious,
widget.previousBtnTitle,
i,
) ==
null)
? MainAxisAlignment.start
: widget.steps.first != widget.steps[i]
? MainAxisAlignment.center
: MainAxisAlignment.end,
children: [
Row(
mainAxisAlignment:
widget.buttonMainAxisAlignment != null
? widget.buttonMainAxisAlignment!
: (widget.previousButtonBuilder !=
null &&
widget.previousButtonBuilder
?.call(
onPrevious,
widget
.previousBtnTitle,
i,
) ==
null)
? MainAxisAlignment.start
: widget.steps.first !=
widget.steps[i]
? MainAxisAlignment.center
: MainAxisAlignment.end,
children: [
if (widget.previousButtonBuilder ==
null) ...[
if (widget.steps.first !=
widget.steps[i])
ElevatedButton(
onPressed: onPrevious,
child: Row(
children: [
const Icon(
Icons.arrow_back,
size: 18,
),
Padding(
padding:
const EdgeInsets.only(
left: 4.0),
child: Text(
widget.previousBtnTitle),
),
],
if (widget.previousButtonBuilder == null) ...[
if (widget.steps.first != widget.steps[i])
ElevatedButton(
onPressed: onPrevious,
child: Row(
children: [
const Icon(
Icons.arrow_back,
size: 18,
),
),
] else if (widget.previousButtonBuilder
?.call(onPrevious,
widget.previousBtnTitle, i) !=
null) ...[
widget.previousButtonBuilder!.call(
onPrevious,
widget.previousBtnTitle,
i)!
],
widget.nextButtonBuilder?.call(
!_formValid
? null
: () async {
await onNext(
widget.steps[i]);
},
widget.steps.last == widget.steps[i]
? widget.submitBtnTitle
: widget.nextBtnTitle,
i,
_formValid,
) ??
ElevatedButton(
onPressed: !_formValid
? null
: () async {
await onNext(
widget.steps[i]);
},
child: Row(
children: [
Text(
widget.steps.last ==
widget.steps[i]
? widget.submitBtnTitle
: widget.nextBtnTitle,
),
const Padding(
padding: EdgeInsets.only(
left: 4.0),
child: Icon(
Icons.arrow_forward,
size: 18,
),
),
],
Padding(
padding: const EdgeInsets.only(
left: 4.0),
child:
Text(widget.previousBtnTitle),
),
),
],
),
if (widget.loginButton != null)
Padding(
padding: const EdgeInsets.only(top: 20.0),
child: widget.loginButton!,
),
],
),
),
] else if (widget.previousButtonBuilder?.call(
onPrevious,
widget.previousBtnTitle,
i) !=
null) ...[
widget.previousButtonBuilder!.call(
onPrevious, widget.previousBtnTitle, i)!
],
widget.nextButtonBuilder?.call(
!_formValid
? null
: () async {
await onNext(widget.steps[i]);
},
widget.steps.last == widget.steps[i]
? widget.submitBtnTitle
: widget.nextBtnTitle,
i,
_formValid,
) ??
ElevatedButton(
onPressed: !_formValid
? null
: () async {
await onNext(widget.steps[i]);
},
child: Row(
children: [
Text(
widget.steps.last ==
widget.steps[i]
? widget.submitBtnTitle
: widget.nextBtnTitle,
),
const Padding(
padding:
EdgeInsets.only(left: 4.0),
child: Icon(
Icons.arrow_forward,
size: 18,
),
),
],
),
),
],
),
if (widget.loginButton != null)
Padding(
padding: const EdgeInsets.only(top: 20.0),
child: widget.loginButton!,
),
],
]),
]),
));
),
],
],
),
],
),
),
);
}
}

View file

@ -7,6 +7,7 @@ import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_registration/flutter_registration.dart';
/// A set of options for configuring the registration process in a Flutter application.
class RegistrationOptions {
RegistrationOptions({
required this.registrationRepository,
@ -23,21 +24,67 @@ class RegistrationOptions {
this.loginButton,
});
/// Translations for registration-related messages and prompts.
final RegistrationTranslations registrationTranslations;
/// The steps involved in the registration process.
final List<AuthStep> registrationSteps;
/// A function that handles errors during registration.
final int? Function(String error)? onError;
/// A callback function executed after successful registration.
final VoidCallback afterRegistration;
/// The repository responsible for registration.
final RegistrationRepository registrationRepository;
/// A function for customizing the app bar displayed during registration.
final AppBar Function(String title)? customAppbarBuilder;
/// A function for customizing the "Next" button.
final Widget Function(Future<void> Function()? onPressed, String label,
int step, 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.
Widget? titleWidget;
/// A custom widget for displaying a login button.
Widget? loginButton;
/// 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({
TextEditingController? emailController,
TextEditingController? pass1Controller,
@ -61,19 +108,12 @@ class RegistrationOptions {
name: 'email',
textEditingController: emailController,
value: initialEmail ?? '',
title: titleBuilder?.call(
translations.defaultEmailTitle,
) ??
title: titleBuilder?.call(translations.defaultEmailTitle) ??
Padding(
padding: const EdgeInsets.only(
top: 24.0,
bottom: 12.0,
),
padding: const EdgeInsets.only(top: 24.0, bottom: 12.0),
child: Text(
translations.defaultEmailTitle,
style: const TextStyle(
fontWeight: FontWeight.bold,
),
style: const TextStyle(fontWeight: FontWeight.bold),
),
),
textFieldDecoration: InputDecoration(
@ -99,19 +139,12 @@ class RegistrationOptions {
AuthPassField(
name: 'password1',
textEditingController: pass1Controller,
title: titleBuilder?.call(
translations.defaultPassword1Title,
) ??
title: titleBuilder?.call(translations.defaultPassword1Title) ??
Padding(
padding: const EdgeInsets.only(
top: 24.0,
bottom: 12.0,
),
padding: const EdgeInsets.only(top: 24.0, bottom: 12.0),
child: Text(
translations.defaultPassword1Title,
style: const TextStyle(
fontWeight: FontWeight.bold,
),
style: const TextStyle(fontWeight: FontWeight.bold),
),
),
textFieldDecoration: InputDecoration(
@ -131,19 +164,12 @@ class RegistrationOptions {
AuthPassField(
name: 'password2',
textEditingController: pass2Controller,
title: titleBuilder?.call(
translations.defaultPassword2Title,
) ??
title: titleBuilder?.call(translations.defaultPassword2Title) ??
Padding(
padding: const EdgeInsets.only(
top: 24.0,
bottom: 12.0,
),
padding: const EdgeInsets.only(top: 24.0, bottom: 12.0),
child: Text(
translations.defaultPassword2Title,
style: const TextStyle(
fontWeight: FontWeight.bold,
),
style: const TextStyle(fontWeight: FontWeight.bold),
),
),
textFieldDecoration: InputDecoration(

View file

@ -6,7 +6,27 @@ 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,

View file

@ -1,7 +1,11 @@
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,
@ -15,12 +19,25 @@ class AuthDropdownField extends AuthField {
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

View file

@ -4,7 +4,21 @@
import 'package:flutter/material.dart';
/// An abstract class representing a field in a Flutter form.
///
/// [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({
required this.name,
required this.value,
@ -13,12 +27,25 @@ abstract class AuthField<T> {
this.validators = const [],
});
/// The name of the field.
final String name;
final Widget? title;
List<String? Function(T?)> validators;
/// The initial value of the field.
T value;
final Function(T)? onValueChanged; // Callback for value changes
/// 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);
}

View file

@ -6,7 +6,31 @@ 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,
TextEditingController? textEditingController,

View file

@ -5,7 +5,29 @@
import 'package:flutter/material.dart';
import 'package:flutter_registration/flutter_registration.dart';
/// A field for capturing text inputs in a Flutter form.
///
/// 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({
required super.name,
TextEditingController? textEditingController,

View file

@ -4,21 +4,28 @@ import 'package:flutter/material.dart';
import 'package:flutter_registration/flutter_registration.dart';
import 'package:flutter_registration/src/auth_screen.dart';
/// A screen for user registration.
class RegistrationScreen extends StatefulWidget {
/// Constructs a [RegistrationScreen] object.
///
/// [registrationOptions] specifies the registration options.
const RegistrationScreen({
required this.registrationOptions,
Key? key,
}) : super(key: key);
/// The registration options.
final RegistrationOptions registrationOptions;
@override
RegistrationScreenState createState() => RegistrationScreenState();
}
/// The state for [RegistrationScreen].
class RegistrationScreenState extends State<RegistrationScreen> {
bool _isLoading = false;
/// Registers the user.
Future<void> _register({
required HashMap<String, dynamic> values,
required void Function(int? pageToReturn) onError,