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 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 # 2.0.0
- feat(buttons): Added the possiblity to only have a next button by return zero on the previous button builder - 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: exposed input decoration in AuthTextField

View file

@ -26,6 +26,7 @@ class AuthScreen extends StatefulWidget {
this.formFlex, this.formFlex,
this.beforeTitleFlex, this.beforeTitleFlex,
this.afterTitleFlex, this.afterTitleFlex,
this.isLoading = false,
super.key, super.key,
}) : assert(steps.length > 0, 'At least one step is required'); }) : assert(steps.length > 0, 'At least one step is required');
@ -51,6 +52,7 @@ class AuthScreen extends StatefulWidget {
final int? formFlex; final int? formFlex;
final int? beforeTitleFlex; final int? beforeTitleFlex;
final int? afterTitleFlex; final int? afterTitleFlex;
final bool isLoading;
@override @override
State<AuthScreen> createState() => _AuthScreenState(); State<AuthScreen> createState() => _AuthScreenState();
@ -140,7 +142,15 @@ class _AuthScreenState extends State<AuthScreen> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return widget.isLoading
? const Center(
child: SizedBox(
height: 120,
width: 120,
child: CircularProgressIndicator(),
),
)
: Scaffold(
backgroundColor: widget.customBackgroundColor ?? Colors.white, backgroundColor: widget.customBackgroundColor ?? Colors.white,
appBar: _appBar, appBar: _appBar,
body: Form( body: Form(
@ -161,34 +171,14 @@ class _AuthScreenState extends State<AuthScreen> {
mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
Spacer( Expanded(
flex: widget.beforeTitleFlex ?? 3, flex: widget.beforeTitleFlex ?? 3,
child: Container(),
), ),
widget.titleWidget!, widget.titleWidget!,
Spacer( Expanded(
flex: widget.afterTitleFlex ?? 2, flex: widget.afterTitleFlex ?? 2,
), child: Container(),
],
),
),
],
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);
}),
],
),
), ),
], ],
), ),
@ -199,20 +189,26 @@ class _AuthScreenState extends State<AuthScreen> {
mainAxisAlignment: mainAxisAlignment:
widget.buttonMainAxisAlignment != null widget.buttonMainAxisAlignment != null
? widget.buttonMainAxisAlignment! ? widget.buttonMainAxisAlignment!
: (widget.previousButtonBuilder != null && : (widget.previousButtonBuilder !=
widget.previousButtonBuilder?.call( null &&
widget.previousButtonBuilder
?.call(
onPrevious, onPrevious,
widget.previousBtnTitle, widget
.previousBtnTitle,
i, i,
) == ) ==
null) null)
? MainAxisAlignment.start ? MainAxisAlignment.start
: widget.steps.first != widget.steps[i] : widget.steps.first !=
widget.steps[i]
? MainAxisAlignment.center ? MainAxisAlignment.center
: MainAxisAlignment.end, : MainAxisAlignment.end,
children: [ children: [
if (widget.previousButtonBuilder == null) ...[ if (widget.previousButtonBuilder ==
if (widget.steps.first != widget.steps[i]) null) ...[
if (widget.steps.first !=
widget.steps[i])
ElevatedButton( ElevatedButton(
onPressed: onPrevious, onPressed: onPrevious,
child: Row( child: Row(
@ -222,23 +218,30 @@ class _AuthScreenState extends State<AuthScreen> {
size: 18, size: 18,
), ),
Padding( Padding(
padding: const EdgeInsets.only(left: 4.0), padding:
child: Text(widget.previousBtnTitle), const EdgeInsets.only(
left: 4.0),
child: Text(
widget.previousBtnTitle),
), ),
], ],
), ),
), ),
] else if (widget.previousButtonBuilder?.call( ] else if (widget.previousButtonBuilder
onPrevious, widget.previousBtnTitle, i) != ?.call(onPrevious,
widget.previousBtnTitle, i) !=
null) ...[ null) ...[
widget.previousButtonBuilder! widget.previousButtonBuilder!.call(
.call(onPrevious, widget.previousBtnTitle, i)! onPrevious,
widget.previousBtnTitle,
i)!
], ],
widget.nextButtonBuilder?.call( widget.nextButtonBuilder?.call(
!_formValid !_formValid
? null ? null
: () async { : () async {
await onNext(widget.steps[i]); await onNext(
widget.steps[i]);
}, },
widget.steps.last == widget.steps[i] widget.steps.last == widget.steps[i]
? widget.submitBtnTitle ? widget.submitBtnTitle
@ -250,17 +253,20 @@ class _AuthScreenState extends State<AuthScreen> {
onPressed: !_formValid onPressed: !_formValid
? null ? null
: () async { : () async {
await onNext(widget.steps[i]); await onNext(
widget.steps[i]);
}, },
child: Row( child: Row(
children: [ children: [
Text( Text(
widget.steps.last == widget.steps[i] widget.steps.last ==
widget.steps[i]
? widget.submitBtnTitle ? widget.submitBtnTitle
: widget.nextBtnTitle, : widget.nextBtnTitle,
), ),
const Padding( const Padding(
padding: EdgeInsets.only(left: 4.0), padding: EdgeInsets.only(
left: 4.0),
child: Icon( child: Icon(
Icons.arrow_forward, Icons.arrow_forward,
size: 18, size: 18,
@ -279,10 +285,8 @@ class _AuthScreenState extends State<AuthScreen> {
], ],
), ),
], ],
), ]),
], ]),
), ));
),
);
} }
} }

View file

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

View file

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