In the last post we created the UI for the Contacts Page. Today we’ll be creating the UI for adding a new contact and also writing the ContactsBloc to support the business logic for the Contacts Page.

It’s already 1 a.m. at the time of writing this post and that’s because I got stuck at quite a few things while doing this task, You know those weird errors and issues you just seem to have no solution to sometimes!

But thankfully I was able to fix them and so here we go. Let’s start!

Animating the FloatingActionButton and the Add-User ModalSheet

Before diving into the code let’s see what we’ll be building.

To start with we need a BottomSheet with rounded top corners. The default BottomSheet has a weird issue with TextField widget. It does not push the TextField up when keyboard is displayed and thus the TextField gets hidden behind it. There’s a workaround for it and we’ll be using the modifed BottomSheetFixed.dart from here to fix it.

Create the showAddContactsBottomSheet method.

It uses a BoxDecoration for the rounded edges. The GradientFab is the same from the last post.

The getButtonChild method returns the Icon for the FAB based on the state.

Creating The ContactsBloc

Create the ContactsBloc inside blocs/contacts using the BlocGenerator plugin. Or else create it manually. Once generated you should have the following file structure.

I’ve explained what they are in a old post here.

Create the States and the Events

Let’s now create the Bloc for mapping events to state.

This should give you a visual blueprint of which event does what. Now we need to implement the underlying logic of interaction with Firebase.

The Problem

I wanted to have a unique constraint on username field, so that duplicate contacts or profiles can’t be created. Unfortunately Firebase out of the box does not come with a Unique constraint.

The solution to this is to maintain a mapping of uid-> username and username->uid . We already have a mapping of uid->username under /users collection on our FireStore. Let’s create the second mapping.

Also update and add rules for this in the rules section of FireStore.

https://gist.github.com/adityadroid/1ce127903133ba471f352ad2e105c351

Retrieving Session Uid from Firebase each time is a bit slow. Let’s cache it in our local preferences. Add this to your pubspec.yaml dependencies.

shared_preferences: ^0.5.3+4

Create Utils/SharedObjects and define a global SharedPreferences

We’ll be saving the Uid in SharedPreferences with signInWithGoogle method of AuthenticationProvider .

Now let’s write the add and fetch contact methods in UserDataProvider . For fetching the data we’ll be using a Stream.

For handing errors on the UI we’re throwing custom exceptions for each condition encountered. Let’s see what these exceptions are.

Wiring the Bloc with the UI

Our Bloc is ready to be wired with the UI. We’re using BlocBuilder and BlocListener to respond to different states.

And that’s it for today. The tests will all fail because we haven’t updated them with a mocked version of SharedPreferences . I’ll be working on that and other stuff tomorrow.

Hit me up in the comments below or Twitter or Linkedin or Instagram if you have any queries or suggestions or just for a casual tech talk maybe? See you guys in the next one!

Code Changes

#18 Contact Bloc

#19Replaced State for contactlist with Stream

How Can You Contribute?

Open issues with suggestion of better approaches or ideas for the app.

Connect with me on Twitter or Linkedin or Instagram.

Star the Github repository.

Share the series on Twitter.

Follow me on Github.

Posts In This Series

Show Your Support

Press the clap button below if you liked reading this post. The more you clap the more it motivates me to write better!