In the last post we finished our contacts page. The next thing a user would do from the contacts page, is to click on the Contact, which would open the Chat Page. We already built the UI for the Chat Page few weeks ago. Today we’ll be writing the Business logic and the Providers to handle the sending and receiving of the messages to and from Firebase.

Generate the Bloc

Generate your bloc using Bloc Generator at blocs/chats . Something like this.

Our Chat Screen can have atmost three states. The InitialState , the FetchedMessagesState (when the messages are retrieved from Firebase) and ErrorState in case of any errors.

And the possible events can be FetchMessagesEvent (triggered when chat opens), ReceivedMessagesEvent (triggered when messages stream has any updates to deliver), SendTextMessageEvent (used to send a normal text message). PickedAttachmentEvent ( when the user has picked a attachment as a message).

We have talked about the States and the Events but the most important part of the Chat Screen are the messages. We can have 4 types of messages in our case.

TextMessage

ImageMessage

VideoMessage

FileMessage

To simplify and to make the process of adding more message types in the future(if required) we’ll abstract out the core properties and methods of our Message class. All the children types should then inherit and implement these properties and methods.

Firestore Structure

Our Firestore DB for the chats will look something like this.

Here, chat1 is a chat between the participants ‘ron’ and ‘smith’. All the messages in this chat will be part of the messages Collection under chat. So we’ll need to read the messages from /chats/chat_id/messages . We also need to retrieve the last message from the chat, (for the homepage view where just the last message is shown). This technique of improving read speeds by duplicating data is called Fanning, in NOSQL Databases.

Also add these rules to your Firestore DB rules.

match /chats/{document=**} {



function isSignedIn() {

return request.auth.uid != null;

}



allow create, read, update, delete : if isSignedIn();

}

At the end of the series we’ll write secure rules for all the reads and writes. Right now I’m just allowing r/w to anyone who is signed in.

The ChatProvider

The job of the ChatProvider will be to facilitate reading and writing of the messages from the /chats Collection.

Like in previous posts, I’ve avoided creating a concrete implementation and created a BaseChatProvider which contains the declaration of all the methods. Architecturing like this helps in future modifications.

Check the Code Changes section or this if you want to have a look at how the BaseProviders and the Repositories are structured.

The Bloc

And lastly we’ll write the ChatBloc for mapping Events to States .

For sending normal text messages we’re just using the chatRepository.sendMessage method. For receiving them we’re using a Stream. Since we do not want our Stream to be directly communicating with the UI but instead go through a Bloc State , we’re triggering another Event which yields a State with updated data.

Do notice that in the mapPickedAttachmentEventToState method we aren’t yet checking for the FileType and directly assuming that it is a VideoMessage . We’ll fix this when we wire our Bloc with the UI and also iron out the other little things.

I’ve also updated the tests for the ContactsBloc post, so do check them out, it includes testing streams which is something I haven’t covered yet in my blog. So that’s it, we’re done for the day!

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

#20 Created the ChatBloc

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!