Merge pull request #19 from Iconica-Development/feat/registration-progress-indicator

feat(registration): add progress indicator for on finish
This commit is contained in:
Freek van de Ven 2024-02-15 17:45:35 +01:00 committed by GitHub
commit 7a4bcd8b3f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 184 additions and 162 deletions

View file

@ -3,6 +3,11 @@ SPDX-FileCopyrightText: 2022 Iconica
SPDX-License-Identifier: GPL-3.0-or-later
-->
# 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

View file

@ -26,6 +26,7 @@ class AuthScreen extends StatefulWidget {
this.formFlex,
this.beforeTitleFlex,
this.afterTitleFlex,
this.isLoading = false,
super.key,
}) : assert(steps.length > 0, 'At least one step is required');
@ -51,6 +52,7 @@ class AuthScreen extends StatefulWidget {
final int? formFlex;
final int? beforeTitleFlex;
final int? afterTitleFlex;
final bool isLoading;
@override
State<AuthScreen> createState() => _AuthScreenState();
@ -140,149 +142,151 @@ class _AuthScreenState extends State<AuthScreen> {
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: widget.customBackgroundColor ?? Colors.white,
appBar: _appBar,
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: [
Spacer(
flex: widget.beforeTitleFlex ?? 3,
),
widget.titleWidget!,
Spacer(
flex: widget.afterTitleFlex ?? 2,
),
],
),
),
],
Flexible(
flex: widget.formFlex ?? 3,
child: Column(
children: [
for (AuthField field in widget.steps[i].fields)
Align(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (field.title != null) ...[
field.title!,
],
field.build(context, () {
_validate(i);
}),
],
),
),
],
),
),
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: [
if (widget.previousButtonBuilder == null) ...[
if (widget.steps.first != widget.steps[i])
ElevatedButton(
onPressed: onPrevious,
child: Row(
return widget.isLoading
? const Center(
child: SizedBox(
height: 120,
width: 120,
child: CircularProgressIndicator(),
),
)
: Scaffold(
backgroundColor: widget.customBackgroundColor ?? Colors.white,
appBar: _appBar,
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: [
const Icon(
Icons.arrow_back,
size: 18,
Expanded(
flex: widget.beforeTitleFlex ?? 3,
child: Container(),
),
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: [
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),
),
],
),
),
] 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(left: 4.0),
child: Text(widget.previousBtnTitle),
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

@ -1,61 +1,74 @@
// SPDX-FileCopyrightText: 2022 Iconica
//
// SPDX-License-Identifier: BSD-3-Clause
import 'dart:collection';
import 'package:flutter/material.dart';
import 'package:flutter_registration/flutter_registration.dart';
import 'package:flutter_registration/src/auth_screen.dart';
class RegistrationScreen extends StatelessWidget {
class RegistrationScreen extends StatefulWidget {
const RegistrationScreen({
required this.registrationOptions,
super.key,
});
Key? key,
}) : super(key: key);
final RegistrationOptions registrationOptions;
Future<void> register({
@override
RegistrationScreenState createState() => RegistrationScreenState();
}
class RegistrationScreenState extends State<RegistrationScreen> {
bool _isLoading = false;
Future<void> _register({
required HashMap<String, dynamic> values,
required void Function(int? pageToReturn) onError,
}) async {
try {
var registered =
await registrationOptions.registrationRepository.register(values);
setState(() {
_isLoading = true;
});
var registered = await widget.registrationOptions.registrationRepository
.register(values);
if (registered == null) {
registrationOptions.afterRegistration();
widget.registrationOptions.afterRegistration();
} else {
var pageToReturn = registrationOptions.onError?.call(registered);
var pageToReturn = widget.registrationOptions.onError?.call(registered);
onError(pageToReturn);
}
} catch (e) {
onError(0);
} finally {
setState(() {
_isLoading = false;
});
}
}
@override
Widget build(BuildContext context) {
var translations = registrationOptions.registrationTranslations;
var translations = widget.registrationOptions.registrationTranslations;
return AuthScreen(
steps: registrationOptions.registrationSteps,
customAppBar: registrationOptions.customAppbarBuilder?.call(
steps: widget.registrationOptions.registrationSteps,
customAppBar: widget.registrationOptions.customAppbarBuilder?.call(
translations.title,
),
onFinish: register,
onFinish: _register,
appBarTitle: translations.title,
submitBtnTitle: translations.registerBtn,
nextBtnTitle: translations.nextStepBtn,
previousBtnTitle: translations.previousStepBtn,
nextButtonBuilder: registrationOptions.nextButtonBuilder,
previousButtonBuilder: registrationOptions.previousButtonBuilder,
buttonMainAxisAlignment: registrationOptions.buttonMainAxisAlignment,
customBackgroundColor: registrationOptions.backgroundColor,
titleWidget: registrationOptions.titleWidget,
loginButton: registrationOptions.loginButton,
nextButtonBuilder: widget.registrationOptions.nextButtonBuilder,
previousButtonBuilder: widget.registrationOptions.previousButtonBuilder,
buttonMainAxisAlignment:
widget.registrationOptions.buttonMainAxisAlignment,
customBackgroundColor: widget.registrationOptions.backgroundColor,
titleWidget: widget.registrationOptions.titleWidget,
loginButton: widget.registrationOptions.loginButton,
isLoading: _isLoading,
);
}
}

View file

@ -4,7 +4,7 @@
name: flutter_registration
description: A Flutter Registration package
version: 2.0.0
version: 2.0.1
repository: https://github.com/Iconica-Development/flutter_registration
publish_to: none