Flutter sign in : Firebase, Provider web app

As we were discussing flutter 3.0 web app, we had hard coded the initial blog data. There was no flutter sign in method so that the user could log in.

It’s true that we had not introduced Firebase and Flutter sign in methods in our previous discussion. Still we had progressed a little bit.

Initially our Firebase, Provider web app looked like the following.

User can select a portion of text with selectable text in flutter
User can select a portion of text with selectable text in flutter

We have changed the look a little bit.

As a result, the web app now looks as follows. 

Flutter sign in, home page
Flutter sign in, home page

As a whole we are still not happy with the home page design, but we will work on it later.

Similarly, we will later adopt material 3 design that flutter 3.0 allows us to apply.

At present regarding this flutter sign in topic, let’s see how we can first write our business logic.

To begin with we need to go to the Firebase and create a project.

Secondly, we have discussed how to create a Firebase project before. Therefore, we’re not repeating the same procedure again. 

Flutter sign in business logic

Instead let’s concentrate on how we can write the business logic.

Certainly we have added all the dependencies to our pubspec.yaml file, all the same that was the beginning.

Real work starts from the Firebase email authentication page.

Why?

Because we have enabled the flutter sign in methods. 

Flutter sign in with Firebase
Flutter sign in with Firebase

As a result on Firebase email authentication page we see a bunch of users’ names.

In addition, in the pubspec.yaml file we have seen all the dependencies.

dependencies:
  flutter:
    sdk: flutter


  # The following adds the Cupertino Icons font to your application.
  # Use with the CupertinoIcons class for iOS style icons.
  cupertino_icons: ^1.0.2
  firebase_core: ^1.14.0
  firebase_auth: ^3.3.13
  cloud_firestore: ^3.1.11
  google_fonts: ^2.3.1
  provider: ^6.0.2

In the same vein, we can now write the flutter sign in business logic where we can test the current status of the user.

For that we have used enums. By the way, we have an article on enums earlier, you may check.

We have kept this flutter sign in logic in our controller folder.

import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';

import 'all_types_of_custom_forms.dart';
import 'all_widgets.dart';

enum UserStatus {
  loggedOut,
  emailAddress,
  register,
  password,
  loggedIn,
}

class AuthenticationForFirebase extends StatelessWidget {
  const AuthenticationForFirebase({
    required this.loginState,
    required this.email,
    required this.startLoginFlow,
    required this.verifyEmail,
    required this.signInWithEmailAndPassword,
    required this.cancelRegistration,
    required this.registerAccount,
    required this.signOut,
  });

  final UserStatus loginState;
  final String? email;
  final void Function() startLoginFlow;
  final void Function(
    String email,
    void Function(Exception e) error,
  ) verifyEmail;
  final void Function(
    String email,
    String password,
    void Function(Exception e) error,
  ) signInWithEmailAndPassword;
  final void Function() cancelRegistration;
  final void Function(
    String email,
    String displayName,
    String password,
    void Function(Exception e) error,
  ) registerAccount;
  final void Function() signOut;

  @override
  Widget build(BuildContext context) {
    switch (loginState) {
      case UserStatus.loggedOut:
        return Row(
          children: [
            Padding(
              padding: const EdgeInsets.only(left: 24, bottom: 8),
              child: StyledButton(
                onPressed: () {
                  startLoginFlow();
                },
                child: Text(
                  'SignIn/Register',
                  style: GoogleFonts.laila(
                    fontSize: 30.0,
                    fontWeight: FontWeight.bold,
                  ),
                ),
              ),
            ),
          ],
        );
      case UserStatus.emailAddress:
        return CutomEmailForm(
            callback: (email) => verifyEmail(
                email, (e) => _showErrorDialog(context, 'Invalid email', e)));
      case UserStatus.password:
        return CustomPasswordForm(
          email: email!,
          login: (email, password) {
            signInWithEmailAndPassword(email, password,
                (e) => _showErrorDialog(context, 'Failed to sign in', e));
          },
        );
      case UserStatus.register:
        return CustomRegistrationForm(
          email: email!,
          cancel: () {
            cancelRegistration();
          },
          registerAccount: (
            email,
            displayName,
            password,
          ) {
            registerAccount(
                email,
                displayName,
                password,
                (e) =>
                    _showErrorDialog(context, 'Failed to create account', e));
          },
        );
      case UserStatus.loggedIn:
        return Row(
          children: [
            Padding(
              padding: const EdgeInsets.only(left: 24, bottom: 8),
              child: StyledButton(
                onPressed: () {
                  signOut();
                },
                child: const Text('LOGOUT'),
              ),
            ),
          ],
        );
      default:
        return Row(
          children: const [
            Text("Internal error, this shouldn't happen..."),
          ],
        );
    }
  }

  void _showErrorDialog(BuildContext context, String title, Exception e) {
    showDialog<void>(
      context: context,
      builder: (context) {
        return AlertDialog(
          title: Text(
            title,
            style: const TextStyle(fontSize: 24),
          ),
          content: SingleChildScrollView(
            child: ListBody(
              children: <Widget>[
                Text(
                  '${(e as dynamic).message}',
                  style: const TextStyle(fontSize: 18),
                ),
              ],
            ),
          ),
          actions: <Widget>[
            StyledButton(
              onPressed: () {
                Navigator.of(context).pop();
              },
              child: const Text(
                'OK',
                style: TextStyle(color: Colors.deepPurple),
              ),
            ),
          ],
        );
      },
    );
  }
}

At any rate now our app will know the user’s status. That means, whether the user is a new user, or an existing user.

An existing user can sign in and start writing blogs.

Flutter sign in page
Flutter sign in page

However, our app will check the application state and allow a new user to register.

In the next section, we will discuss that part in detail.

What Next?

Books at Leanpub
Books in Apress
My books at Amazon
GitHub repository
Python and Data Science
Twitter


Posted

in

, , , ,

by

Comments

One response to “Flutter sign in : Firebase, Provider web app”

  1. […] need to increase the size because we’ve been building a Flutter Firebase, Provider web app where users write […]

Leave a Reply