From dafa9e157af965edcc9b82f22c83c3ba5ea850a5 Mon Sep 17 00:00:00 2001 From: Pierre HUBERT Date: Sat, 17 Apr 2021 09:52:05 +0200 Subject: [PATCH] Create login widget --- lib/helpers/account_helper.dart | 10 ++- lib/ui/routes/login_route.dart | 110 ++----------------------------- lib/ui/widgets/login_widget.dart | 109 ++++++++++++++++++++++++++++++ 3 files changed, 118 insertions(+), 111 deletions(-) create mode 100644 lib/ui/widgets/login_widget.dart diff --git a/lib/helpers/account_helper.dart b/lib/helpers/account_helper.dart index 073cef7..d21a580 100644 --- a/lib/helpers/account_helper.dart +++ b/lib/helpers/account_helper.dart @@ -1,4 +1,3 @@ -import 'package:comunic/helpers/api_helper.dart'; import 'package:comunic/helpers/preferences_helper.dart'; import 'package:comunic/helpers/push_notifications_helper.dart'; import 'package:comunic/helpers/websocket_helper.dart'; @@ -44,11 +43,10 @@ class AccountHelper { /// Sign in user Future signIn(AuthenticationDetails auth) async { - final request = APIRequest(uri: "account/login"); - request.addString("mail", auth.email); - request.addString("password", auth.password); - - final response = await APIHelper().exec(request); + final response = await APIRequest.withoutLogin("account/login") + .addString("mail", auth.email) + .addString("password", auth.password) + .exec(); // Handle errors if (response.code == 401) diff --git a/lib/ui/routes/login_route.dart b/lib/ui/routes/login_route.dart index 26a4977..7204f10 100644 --- a/lib/ui/routes/login_route.dart +++ b/lib/ui/routes/login_route.dart @@ -1,12 +1,9 @@ -import 'package:comunic/helpers/account_helper.dart'; -import 'package:comunic/models/authentication_details.dart'; import 'package:comunic/ui/routes/create_account_route.dart'; import 'package:comunic/ui/routes/forgot_password_route.dart'; import 'package:comunic/ui/widgets/init_widget.dart'; import 'package:comunic/ui/widgets/login_scaffold.dart'; -import 'package:comunic/utils/input_utils.dart'; +import 'package:comunic/ui/widgets/login_widget.dart'; import 'package:comunic/utils/intl_utils.dart'; -import 'package:comunic/utils/ui_utils.dart'; import 'package:flutter/material.dart'; /// Login route @@ -19,49 +16,6 @@ class LoginRoute extends StatefulWidget { } class _LoginRouteState extends State { - String _currEmail; - String _currPassword; - AuthResult _authResult; - bool _loading = false; - - @override - void initState() { - super.initState(); - _currEmail = ""; - _currPassword = ""; - } - - void _emailChanged(String newEmail) { - setState(() { - _currEmail = newEmail; - }); - } - - void _passwordChanged(String newValue) { - setState(() { - _currPassword = newValue; - }); - } - - /// Call this whenever the user request to perform login - Future _submitForm(BuildContext context) async { - setState(() { - _loading = true; - }); - - final loginResult = await AccountHelper().signIn( - AuthenticationDetails(email: _currEmail, password: _currPassword)); - - if (loginResult == AuthResult.SUCCESS) - Navigator.pushReplacement( - context, MaterialPageRoute(builder: (b) => InitializeWidget())); - else - setState(() { - _authResult = loginResult; - _loading = false; - }); - } - void _openCreateAccountPage() { Navigator.of(context) .push(MaterialPageRoute(builder: (c) => CreateAccountRoute())); @@ -72,67 +26,17 @@ class _LoginRouteState extends State { .push(MaterialPageRoute(builder: (c) => ForgotPasswordRoute())); } - /// Build error card - Widget _buildErrorCard() { - if (_authResult == null) return null; - - //Determine the right message - final message = (_authResult == AuthResult.INVALID_CREDENTIALS - ? tr("Invalid credentials!") - : (_authResult == AuthResult.TOO_MANY_ATTEMPTS - ? tr( - "Too many unsuccessfull login attempts! Please try again later...") - : tr("A network error occured!"))); - - return buildErrorCard(message); - } - /// Build login form Widget _buildLoginForm() { - // Whether the form can be submitted or not - final valid = validateEmail(_currEmail) && _currPassword.length >= 3; - return SingleChildScrollView( child: Padding( padding: const EdgeInsets.all(8.0), child: Column( children: [ - Container( - child: _buildErrorCard(), + LoginWidget( + onSignedIn: () => Navigator.pushReplacement(context, + MaterialPageRoute(builder: (b) => InitializeWidget())), ), - //Email address - TextField( - keyboardType: TextInputType.emailAddress, - decoration: InputDecoration( - labelText: tr("Email address"), - alignLabelWithHint: true, - errorText: _currEmail.length > 0 && !validateEmail(_currEmail) - ? tr("Invalid email address!") - : null), - onChanged: _emailChanged, - ), - - //Password - TextField( - obscureText: true, - decoration: InputDecoration( - labelText: tr("Password"), - alignLabelWithHint: true, - ), - onChanged: _passwordChanged, - onSubmitted: valid ? (s) => _submitForm(context) : null, - ), - - Container( - padding: EdgeInsets.all(8.0), - child: _loading - ? CircularProgressIndicator() - : ElevatedButton( - child: Text(tr("Sign in")), - onPressed: valid ? () => _submitForm(context) : null, - ), - ), - InkWell( child: Text( tr("Create an account"), @@ -140,9 +44,7 @@ class _LoginRouteState extends State { ), onTap: () => _openCreateAccountPage(), ), - Container(height: 10), - InkWell( child: Text( tr("Password forgotten"), @@ -157,7 +59,5 @@ class _LoginRouteState extends State { } @override - Widget build(BuildContext context) { - return LoginScaffold(child: _buildLoginForm()); - } + Widget build(BuildContext context) => LoginScaffold(child: _buildLoginForm()); } diff --git a/lib/ui/widgets/login_widget.dart b/lib/ui/widgets/login_widget.dart new file mode 100644 index 0000000..13fa854 --- /dev/null +++ b/lib/ui/widgets/login_widget.dart @@ -0,0 +1,109 @@ +import 'package:comunic/helpers/account_helper.dart'; +import 'package:comunic/models/authentication_details.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/material.dart'; + +/// Login widget +/// +/// Used to authenticate user +/// +/// @author Pierre Hubert + +class LoginWidget extends StatefulWidget { + final void Function() onSignedIn; + + const LoginWidget({Key key, @required this.onSignedIn}) : super(key: key); + + @override + _LoginWidgetState createState() => _LoginWidgetState(); +} + +class _LoginWidgetState extends State { + final _emailEditingController = TextEditingController(); + final _passwordEditionController = TextEditingController(); + bool _loading = false; + AuthResult _authResult; + + String get _currEmail => _emailEditingController.text; + + String get _currPassword => _passwordEditionController.text; + + bool get _canSubmit => validateEmail(_currEmail) && _currPassword.length >= 3; + + /// Build error card + Widget _buildErrorCard() { + if (_authResult == null) return null; + + //Determine the right message + final message = (_authResult == AuthResult.INVALID_CREDENTIALS + ? tr("Invalid credentials!") + : (_authResult == AuthResult.TOO_MANY_ATTEMPTS + ? tr( + "Too many unsuccessful login attempts! Please try again later...") + : tr("A network error occurred!"))); + + return buildErrorCard(message); + } + + @override + Widget build(BuildContext context) => Column( + children: [ + Container( + child: _buildErrorCard(), + ), + //Email address + TextField( + controller: _emailEditingController, + keyboardType: TextInputType.emailAddress, + decoration: InputDecoration( + labelText: tr("Email address"), + alignLabelWithHint: true, + errorText: _currEmail.length > 0 && !validateEmail(_currEmail) + ? tr("Invalid email address!") + : null), + onChanged: (s) => setState(() {}), + ), + + //Password + TextField( + obscureText: true, + decoration: InputDecoration( + labelText: tr("Password"), + alignLabelWithHint: true, + ), + onChanged: (s) => setState(() {}), + onSubmitted: _canSubmit ? (s) => _submitForm(context) : null, + ), + + Container( + padding: EdgeInsets.all(8.0), + child: _loading + ? CircularProgressIndicator() + : ElevatedButton( + child: Text(tr("Sign in")), + onPressed: _canSubmit ? () => _submitForm(context) : null, + ), + ), + ], + ); + + /// Call this whenever the user request to perform login + Future _submitForm(BuildContext context) async { + setState(() { + _loading = true; + }); + + final loginResult = await AccountHelper().signIn( + AuthenticationDetails(email: _currEmail, password: _currPassword)); + + if (loginResult == AuthResult.SUCCESS) + widget.onSignedIn(); + else + setState(() { + _authResult = loginResult; + _loading = false; + }); + } +}