mirror of
				https://gitlab.com/comunic/comunicmobile
				synced 2025-10-30 17:54:57 +00:00 
			
		
		
		
	Refactor code
This commit is contained in:
		| @@ -1,13 +1,7 @@ | ||||
| import 'package:comunic/helpers/account_helper.dart'; | ||||
| import 'package:comunic/helpers/server_config_helper.dart'; | ||||
| import 'package:comunic/models/new_account.dart'; | ||||
| import 'package:comunic/ui/widgets/new_password_input_widget.dart'; | ||||
| import 'package:comunic/utils/input_utils.dart'; | ||||
| import 'package:comunic/ui/widgets/create_account_widget.dart'; | ||||
| import 'package:comunic/utils/intl_utils.dart'; | ||||
| import 'package:comunic/utils/ui_utils.dart'; | ||||
| import 'package:flutter/cupertino.dart'; | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:url_launcher/url_launcher.dart'; | ||||
|  | ||||
| /// Create account route | ||||
| /// | ||||
| @@ -32,222 +26,9 @@ class _CreateAccountRouteBody extends StatefulWidget { | ||||
| } | ||||
|  | ||||
| class __CreateAccountRouteBodyState extends State<_CreateAccountRouteBody> { | ||||
|   final _firstNameController = TextEditingController(); | ||||
|   final _lastNameController = TextEditingController(); | ||||
|   final _emailController = TextEditingController(); | ||||
|   final _passwordInputKey = GlobalKey<NewPasswordInputWidgetState>(); | ||||
|   final _verifyPasswordController = TextEditingController(); | ||||
|   bool _acceptedTOS = false; | ||||
|  | ||||
|   bool _isCreating = false; | ||||
|   CreateAccountResult _createAccountResult; | ||||
|  | ||||
|   bool _showErrors = false; | ||||
|  | ||||
|   bool get _isFirstNameValid => | ||||
|       _firstNameController.text.length >= | ||||
|       srvConfig.accountInformationPolicy.minFirstNameLength; | ||||
|  | ||||
|   bool get _isLastNameValid => | ||||
|       _lastNameController.text.length >= | ||||
|       srvConfig.accountInformationPolicy.minLastNameLength; | ||||
|  | ||||
|   bool get _isEmailValid => validateEmail(_emailController.text); | ||||
|  | ||||
|   bool get _isPasswordValid => _passwordInputKey.currentState.valid; | ||||
|  | ||||
|   bool get _isPasswordConfirmationValid => | ||||
|       _passwordInputKey.currentState != null && | ||||
|       _passwordInputKey.currentState.value == _verifyPasswordController.text; | ||||
|  | ||||
|   bool get _isFormValid => | ||||
|       _isFirstNameValid && | ||||
|       _isLastNameValid && | ||||
|       _isEmailValid && | ||||
|       _isPasswordValid && | ||||
|       _isPasswordConfirmationValid && | ||||
|       _acceptedTOS; | ||||
|  | ||||
|   String get errorMessage => _createAccountResult == | ||||
|           CreateAccountResult.ERROR_EXISTING_EMAIL | ||||
|       ? tr("An account is already associated to this email address!") | ||||
|       : _createAccountResult == CreateAccountResult.ERROR_TOO_MANY_REQUESTS | ||||
|           ? tr( | ||||
|               "Too many accounts have been created from this IP address for now. Please try again later.") | ||||
|           : tr( | ||||
|               "An error occurred while creating your account. Please try again."); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     if (_isCreating) | ||||
|       return Center( | ||||
|         child: CircularProgressIndicator(), | ||||
|       ); | ||||
|  | ||||
|     return Center( | ||||
|       child: Padding( | ||||
|         padding: const EdgeInsets.all(8.0), | ||||
|         child: ConstrainedBox( | ||||
|           constraints: BoxConstraints(maxWidth: 370), | ||||
|           child: ListView( | ||||
|             children: <Widget>[ | ||||
|               _createAccountResult != null | ||||
|                   ? buildErrorCard(errorMessage) | ||||
|                   : Container(), | ||||
|  | ||||
|               // First name | ||||
|               _InputEntry( | ||||
|                 controller: _firstNameController, | ||||
|                 label: tr("First name"), | ||||
|                 onEdited: _updateUI, | ||||
|                 icon: Icon(Icons.perm_identity), | ||||
|                 maxLength: | ||||
|                     srvConfig.accountInformationPolicy.maxFirstNameLength, | ||||
|                 error: _showErrors && !_isFirstNameValid | ||||
|                     ? tr("Invalid first name!") | ||||
|                     : null, | ||||
|               ), | ||||
|  | ||||
|               // Last name | ||||
|               _InputEntry( | ||||
|                 controller: _lastNameController, | ||||
|                 label: tr("Last name"), | ||||
|                 onEdited: _updateUI, | ||||
|                 icon: Icon(Icons.perm_identity), | ||||
|                 maxLength: srvConfig.accountInformationPolicy.maxLastNameLength, | ||||
|                 error: _showErrors && !_isLastNameValid | ||||
|                     ? tr("Invalid last name!") | ||||
|                     : null, | ||||
|               ), | ||||
|  | ||||
|               // Email address | ||||
|               _InputEntry( | ||||
|                 controller: _emailController, | ||||
|                 label: tr("Email address"), | ||||
|                 onEdited: _updateUI, | ||||
|                 icon: Icon(Icons.email), | ||||
|                 keyboard: TextInputType.emailAddress, | ||||
|                 error: _showErrors && !_isEmailValid | ||||
|                     ? tr("Invalid email address!") | ||||
|                     : null, | ||||
|               ), | ||||
|  | ||||
|               // Password | ||||
|               NewPasswordInputWidget( | ||||
|                 key: _passwordInputKey, | ||||
|                 label: tr("Password"), | ||||
|                 onEdited: _updateUI, | ||||
|                 icon: Icon(Icons.lock), | ||||
|                 user: UserInfoForPassword( | ||||
|                   firstName: _firstNameController.text, | ||||
|                   lastName: _lastNameController.text, | ||||
|                   email: _emailController.text, | ||||
|                 ), | ||||
|               ), | ||||
|  | ||||
|               // Verify password | ||||
|               _InputEntry( | ||||
|                 controller: _verifyPasswordController, | ||||
|                 label: tr("Confirm your password"), | ||||
|                 onEdited: _updateUI, | ||||
|                 icon: Icon(Icons.lock_outline), | ||||
|                 isPassword: true, | ||||
|                 error: _showErrors && !_isPasswordConfirmationValid | ||||
|                     ? tr("The password and its confirmation do not match!") | ||||
|                     : null, | ||||
|               ), | ||||
|  | ||||
|               // TOS | ||||
|               CheckboxListTile( | ||||
|                 title: | ||||
|                     Text(tr("I have read and accepted the Terms Of Service.")), | ||||
|                 value: _acceptedTOS, | ||||
|                 onChanged: (b) { | ||||
|                   _acceptedTOS = b; | ||||
|                   _updateUI(); | ||||
|                 }, | ||||
|                 subtitle: _showErrors && !_acceptedTOS | ||||
|                     ? Text( | ||||
|                         tr("You must accept the Terms Of Service to continue."), | ||||
|                         style: TextStyle(color: Colors.redAccent), | ||||
|                       ) | ||||
|                     : null, | ||||
|                 controlAffinity: ListTileControlAffinity.leading, | ||||
|                 secondary: IconButton( | ||||
|                   icon: Icon(Icons.open_in_new), | ||||
|                   onPressed: _openTOS, | ||||
|                 ), | ||||
|               ), | ||||
|  | ||||
|               // Submit button | ||||
|               Center( | ||||
|                 child: ElevatedButton( | ||||
|                   onPressed: _submitForm, | ||||
|                   child: Text("Submit"), | ||||
|                 ), | ||||
|               ), | ||||
|             ], | ||||
|           ), | ||||
|         ), | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   void _updateUI() { | ||||
|     setState(() { | ||||
|       // Nothing yet | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   void _submitForm() async { | ||||
|     if (!_isFormValid) { | ||||
|       _showErrors = true; | ||||
|       _updateUI(); | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|     setState(() { | ||||
|       _isCreating = true; | ||||
|     }); | ||||
|  | ||||
|     final result = await AccountHelper().createAccount(NewAccount( | ||||
|       firstName: _firstNameController.text, | ||||
|       lastName: _lastNameController.text, | ||||
|       email: _emailController.text, | ||||
|       password: _passwordInputKey.currentState.value, | ||||
|     )); | ||||
|  | ||||
|     setState(() { | ||||
|       _isCreating = false; | ||||
|     }); | ||||
|  | ||||
|     if (result != CreateAccountResult.SUCCESS) { | ||||
|       _createAccountResult = result; | ||||
|       _showCreateAccountError(); | ||||
|       _updateUI(); | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|     _accountCreated(); | ||||
|   } | ||||
|  | ||||
|   void _openTOS() => launch(ServerConfigurationHelper.config.termsURL); | ||||
|  | ||||
|   void _showCreateAccountError() async { | ||||
|     await showCupertinoDialog( | ||||
|       context: context, | ||||
|       builder: (c) => CupertinoAlertDialog( | ||||
|         title: Text(tr("Error while creating your account")), | ||||
|         content: Text(errorMessage), | ||||
|         actions: <Widget>[ | ||||
|           CupertinoButton( | ||||
|             child: Text(tr("Ok").toUpperCase()), | ||||
|             onPressed: () => Navigator.of(context).pop(), | ||||
|           ) | ||||
|         ], | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
|   Widget build(BuildContext context) => | ||||
|       CreateAccountWidget(onCreated: _accountCreated); | ||||
|  | ||||
|   void _accountCreated() async { | ||||
|     await showCupertinoDialog( | ||||
| @@ -266,47 +47,3 @@ class __CreateAccountRouteBodyState extends State<_CreateAccountRouteBody> { | ||||
|     Navigator.of(context).pop(); | ||||
|   } | ||||
| } | ||||
|  | ||||
| class _InputEntry extends StatelessWidget { | ||||
|   final TextEditingController controller; | ||||
|   final String label; | ||||
|   final VoidCallback onEdited; | ||||
|   final bool isPassword; | ||||
|   final String error; | ||||
|   final Widget icon; | ||||
|   final TextInputType keyboard; | ||||
|   final int maxLength; | ||||
|  | ||||
|   const _InputEntry({ | ||||
|     Key key, | ||||
|     @required this.controller, | ||||
|     @required this.label, | ||||
|     @required this.onEdited, | ||||
|     this.isPassword = false, | ||||
|     this.error, | ||||
|     this.icon, | ||||
|     this.keyboard, | ||||
|     this.maxLength, | ||||
|   })  : assert(controller != null), | ||||
|         assert(label != null), | ||||
|         assert(onEdited != null), | ||||
|         assert(isPassword != null), | ||||
|         super(key: key); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     return TextField( | ||||
|       controller: controller, | ||||
|       onChanged: (s) => onEdited(), | ||||
|       keyboardType: keyboard, | ||||
|       obscureText: isPassword, | ||||
|       maxLength: maxLength, | ||||
|       decoration: InputDecoration( | ||||
|         alignLabelWithHint: true, | ||||
|         errorText: error, | ||||
|         labelText: label, | ||||
|         icon: icon, | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
| } | ||||
|   | ||||
							
								
								
									
										288
									
								
								lib/ui/widgets/create_account_widget.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										288
									
								
								lib/ui/widgets/create_account_widget.dart
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,288 @@ | ||||
| import 'package:comunic/helpers/account_helper.dart'; | ||||
| import 'package:comunic/helpers/server_config_helper.dart'; | ||||
| import 'package:comunic/models/new_account.dart'; | ||||
| import 'package:comunic/utils/input_utils.dart'; | ||||
| import 'package:comunic/utils/intl_utils.dart'; | ||||
| import 'package:comunic/utils/ui_utils.dart'; | ||||
| import 'package:flutter/cupertino.dart'; | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:url_launcher/url_launcher.dart'; | ||||
|  | ||||
| import 'new_password_input_widget.dart'; | ||||
|  | ||||
| /// Create account widget | ||||
| /// | ||||
| /// @author Pierre Hubert | ||||
|  | ||||
| class CreateAccountWidget extends StatefulWidget { | ||||
|   final void Function() onCreated; | ||||
|  | ||||
|   const CreateAccountWidget({Key key, @required this.onCreated}) | ||||
|       : super(key: key); | ||||
|  | ||||
|   @override | ||||
|   _CreateAccountWidgetState createState() => _CreateAccountWidgetState(); | ||||
| } | ||||
|  | ||||
| class _CreateAccountWidgetState extends State<CreateAccountWidget> { | ||||
|   final _firstNameController = TextEditingController(); | ||||
|   final _lastNameController = TextEditingController(); | ||||
|   final _emailController = TextEditingController(); | ||||
|   final _passwordInputKey = GlobalKey<NewPasswordInputWidgetState>(); | ||||
|   final _verifyPasswordController = TextEditingController(); | ||||
|   bool _acceptedTOS = false; | ||||
|  | ||||
|   bool _isCreating = false; | ||||
|   CreateAccountResult _createAccountResult; | ||||
|  | ||||
|   bool _showErrors = false; | ||||
|  | ||||
|   bool get _isFirstNameValid => | ||||
|       _firstNameController.text.length >= | ||||
|       srvConfig.accountInformationPolicy.minFirstNameLength; | ||||
|  | ||||
|   bool get _isLastNameValid => | ||||
|       _lastNameController.text.length >= | ||||
|       srvConfig.accountInformationPolicy.minLastNameLength; | ||||
|  | ||||
|   bool get _isEmailValid => validateEmail(_emailController.text); | ||||
|  | ||||
|   bool get _isPasswordValid => _passwordInputKey.currentState.valid; | ||||
|  | ||||
|   bool get _isPasswordConfirmationValid => | ||||
|       _passwordInputKey.currentState != null && | ||||
|       _passwordInputKey.currentState.value == _verifyPasswordController.text; | ||||
|  | ||||
|   bool get _isFormValid => | ||||
|       _isFirstNameValid && | ||||
|       _isLastNameValid && | ||||
|       _isEmailValid && | ||||
|       _isPasswordValid && | ||||
|       _isPasswordConfirmationValid && | ||||
|       _acceptedTOS; | ||||
|  | ||||
|   String get errorMessage => _createAccountResult == | ||||
|           CreateAccountResult.ERROR_EXISTING_EMAIL | ||||
|       ? tr("An account is already associated to this email address!") | ||||
|       : _createAccountResult == CreateAccountResult.ERROR_TOO_MANY_REQUESTS | ||||
|           ? tr( | ||||
|               "Too many accounts have been created from this IP address for now. Please try again later.") | ||||
|           : tr( | ||||
|               "An error occurred while creating your account. Please try again."); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     if (_isCreating) | ||||
|       return Center( | ||||
|         child: CircularProgressIndicator(), | ||||
|       ); | ||||
|  | ||||
|     return Center( | ||||
|       child: Padding( | ||||
|         padding: const EdgeInsets.all(8.0), | ||||
|         child: ConstrainedBox( | ||||
|           constraints: BoxConstraints(maxWidth: 370), | ||||
|           child: ListView( | ||||
|             children: <Widget>[ | ||||
|               _createAccountResult != null | ||||
|                   ? buildErrorCard(errorMessage) | ||||
|                   : Container(), | ||||
|  | ||||
|               // First name | ||||
|               _InputEntry( | ||||
|                 controller: _firstNameController, | ||||
|                 label: tr("First name"), | ||||
|                 onEdited: _updateUI, | ||||
|                 icon: Icon(Icons.perm_identity), | ||||
|                 maxLength: | ||||
|                     srvConfig.accountInformationPolicy.maxFirstNameLength, | ||||
|                 error: _showErrors && !_isFirstNameValid | ||||
|                     ? tr("Invalid first name!") | ||||
|                     : null, | ||||
|               ), | ||||
|  | ||||
|               // Last name | ||||
|               _InputEntry( | ||||
|                 controller: _lastNameController, | ||||
|                 label: tr("Last name"), | ||||
|                 onEdited: _updateUI, | ||||
|                 icon: Icon(Icons.perm_identity), | ||||
|                 maxLength: srvConfig.accountInformationPolicy.maxLastNameLength, | ||||
|                 error: _showErrors && !_isLastNameValid | ||||
|                     ? tr("Invalid last name!") | ||||
|                     : null, | ||||
|               ), | ||||
|  | ||||
|               // Email address | ||||
|               _InputEntry( | ||||
|                 controller: _emailController, | ||||
|                 label: tr("Email address"), | ||||
|                 onEdited: _updateUI, | ||||
|                 icon: Icon(Icons.email), | ||||
|                 keyboard: TextInputType.emailAddress, | ||||
|                 error: _showErrors && !_isEmailValid | ||||
|                     ? tr("Invalid email address!") | ||||
|                     : null, | ||||
|               ), | ||||
|  | ||||
|               // Password | ||||
|               NewPasswordInputWidget( | ||||
|                 key: _passwordInputKey, | ||||
|                 label: tr("Password"), | ||||
|                 onEdited: _updateUI, | ||||
|                 icon: Icon(Icons.lock), | ||||
|                 user: UserInfoForPassword( | ||||
|                   firstName: _firstNameController.text, | ||||
|                   lastName: _lastNameController.text, | ||||
|                   email: _emailController.text, | ||||
|                 ), | ||||
|               ), | ||||
|  | ||||
|               // Verify password | ||||
|               _InputEntry( | ||||
|                 controller: _verifyPasswordController, | ||||
|                 label: tr("Confirm your password"), | ||||
|                 onEdited: _updateUI, | ||||
|                 icon: Icon(Icons.lock_outline), | ||||
|                 isPassword: true, | ||||
|                 error: _showErrors && !_isPasswordConfirmationValid | ||||
|                     ? tr("The password and its confirmation do not match!") | ||||
|                     : null, | ||||
|               ), | ||||
|  | ||||
|               // TOS | ||||
|               CheckboxListTile( | ||||
|                 title: | ||||
|                     Text(tr("I have read and accepted the Terms Of Service.")), | ||||
|                 value: _acceptedTOS, | ||||
|                 onChanged: (b) { | ||||
|                   _acceptedTOS = b; | ||||
|                   _updateUI(); | ||||
|                 }, | ||||
|                 subtitle: _showErrors && !_acceptedTOS | ||||
|                     ? Text( | ||||
|                         tr("You must accept the Terms Of Service to continue."), | ||||
|                         style: TextStyle(color: Colors.redAccent), | ||||
|                       ) | ||||
|                     : null, | ||||
|                 controlAffinity: ListTileControlAffinity.leading, | ||||
|                 secondary: IconButton( | ||||
|                   icon: Icon(Icons.open_in_new), | ||||
|                   onPressed: _openTOS, | ||||
|                 ), | ||||
|               ), | ||||
|  | ||||
|               // Submit button | ||||
|               Center( | ||||
|                 child: ElevatedButton( | ||||
|                   onPressed: _submitForm, | ||||
|                   child: Text(tr("Create account")), | ||||
|                 ), | ||||
|               ), | ||||
|             ], | ||||
|           ), | ||||
|         ), | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   void _updateUI() { | ||||
|     setState(() { | ||||
|       // Nothing yet | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   void _submitForm() async { | ||||
|     if (!_isFormValid) { | ||||
|       _showErrors = true; | ||||
|       _updateUI(); | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|     setState(() { | ||||
|       _isCreating = true; | ||||
|     }); | ||||
|  | ||||
|     final result = await AccountHelper().createAccount(NewAccount( | ||||
|       firstName: _firstNameController.text, | ||||
|       lastName: _lastNameController.text, | ||||
|       email: _emailController.text, | ||||
|       password: _passwordInputKey.currentState.value, | ||||
|     )); | ||||
|  | ||||
|     setState(() { | ||||
|       _isCreating = false; | ||||
|     }); | ||||
|  | ||||
|     if (result != CreateAccountResult.SUCCESS) { | ||||
|       _createAccountResult = result; | ||||
|       _showCreateAccountError(); | ||||
|       _updateUI(); | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|     _accountCreated(); | ||||
|   } | ||||
|  | ||||
|   void _openTOS() => launch(ServerConfigurationHelper.config.termsURL); | ||||
|  | ||||
|   void _showCreateAccountError() async { | ||||
|     await showCupertinoDialog( | ||||
|       context: context, | ||||
|       builder: (c) => CupertinoAlertDialog( | ||||
|         title: Text(tr("Error while creating your account")), | ||||
|         content: Text(errorMessage), | ||||
|         actions: <Widget>[ | ||||
|           CupertinoButton( | ||||
|             child: Text(tr("Ok").toUpperCase()), | ||||
|             onPressed: () => Navigator.of(context).pop(), | ||||
|           ) | ||||
|         ], | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
| } | ||||
|  | ||||
| class _InputEntry extends StatelessWidget { | ||||
|   final TextEditingController controller; | ||||
|   final String label; | ||||
|   final VoidCallback onEdited; | ||||
|   final bool isPassword; | ||||
|   final String error; | ||||
|   final Widget icon; | ||||
|   final TextInputType keyboard; | ||||
|   final int maxLength; | ||||
|  | ||||
|   const _InputEntry({ | ||||
|     Key key, | ||||
|     @required this.controller, | ||||
|     @required this.label, | ||||
|     @required this.onEdited, | ||||
|     this.isPassword = false, | ||||
|     this.error, | ||||
|     this.icon, | ||||
|     this.keyboard, | ||||
|     this.maxLength, | ||||
|   })  : assert(controller != null), | ||||
|         assert(label != null), | ||||
|         assert(onEdited != null), | ||||
|         assert(isPassword != null), | ||||
|         super(key: key); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     return TextField( | ||||
|       controller: controller, | ||||
|       onChanged: (s) => onEdited(), | ||||
|       keyboardType: keyboard, | ||||
|       obscureText: isPassword, | ||||
|       maxLength: maxLength, | ||||
|       decoration: InputDecoration( | ||||
|         alignLabelWithHint: true, | ||||
|         errorText: error, | ||||
|         labelText: label, | ||||
|         icon: icon, | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user