mirror of
				https://gitlab.com/comunic/comunicmobile
				synced 2025-11-04 12:14:11 +00:00 
			
		
		
		
	Create login widget
This commit is contained in:
		@@ -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<AuthResult> 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)
 | 
			
		||||
 
 | 
			
		||||
@@ -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<LoginRoute> {
 | 
			
		||||
  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<void> _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<LoginRoute> {
 | 
			
		||||
        .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: <Widget>[
 | 
			
		||||
            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<LoginRoute> {
 | 
			
		||||
              ),
 | 
			
		||||
              onTap: () => _openCreateAccountPage(),
 | 
			
		||||
            ),
 | 
			
		||||
 | 
			
		||||
            Container(height: 10),
 | 
			
		||||
 | 
			
		||||
            InkWell(
 | 
			
		||||
              child: Text(
 | 
			
		||||
                tr("Password forgotten"),
 | 
			
		||||
@@ -157,7 +59,5 @@ class _LoginRouteState extends State<LoginRoute> {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
    return LoginScaffold(child: _buildLoginForm());
 | 
			
		||||
  }
 | 
			
		||||
  Widget build(BuildContext context) => LoginScaffold(child: _buildLoginForm());
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										109
									
								
								lib/ui/widgets/login_widget.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										109
									
								
								lib/ui/widgets/login_widget.dart
									
									
									
									
									
										Normal file
									
								
							@@ -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<LoginWidget> {
 | 
			
		||||
  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<void> _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;
 | 
			
		||||
      });
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user