mirror of
https://gitlab.com/comunic/comunicmobile
synced 2024-11-22 04:49:21 +00:00
Refactor code
This commit is contained in:
parent
7bfbc85d5f
commit
92ab82d7a1
@ -1,13 +1,7 @@
|
|||||||
import 'package:comunic/helpers/account_helper.dart';
|
import 'package:comunic/ui/widgets/create_account_widget.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/utils/intl_utils.dart';
|
import 'package:comunic/utils/intl_utils.dart';
|
||||||
import 'package:comunic/utils/ui_utils.dart';
|
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
|
||||||
|
|
||||||
/// Create account route
|
/// Create account route
|
||||||
///
|
///
|
||||||
@ -32,222 +26,9 @@ class _CreateAccountRouteBody extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class __CreateAccountRouteBodyState extends State<_CreateAccountRouteBody> {
|
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
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) =>
|
||||||
if (_isCreating)
|
CreateAccountWidget(onCreated: _accountCreated);
|
||||||
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(),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void _accountCreated() async {
|
void _accountCreated() async {
|
||||||
await showCupertinoDialog(
|
await showCupertinoDialog(
|
||||||
@ -266,47 +47,3 @@ class __CreateAccountRouteBodyState extends State<_CreateAccountRouteBody> {
|
|||||||
Navigator.of(context).pop();
|
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,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user