60 Days of Flutter :Building a Messenger : Day 42–44 : Creating the Home Page & Quick Peek BottomSheet for Messages
In the last post we created the Attachments Page. We now can add contacts, send/receive messages and attachments in our app. The one key thing missing though is the home page. The reason why I kept the home page for later was because I wasn’t sure of how I wanted it to be. In the end I’ve decided that the user will be able to view all his chats at two different places.
- The Home Page.
- The Chat Screen, using a
BottomSheetwhich is always accessible by sliding over theTextBox.
This is how both of them would look
Create The HomeBloc
Start by generating the HomeBloc at blocs/home using bloc_code_generator. Check this post if you don’t know how to do it.
Let’s define the Events first.
We have two events here.
FetchHomeChatsEventis triggered when the homepage is first opened.ReceivedChatsEventis triggered when there are any updates in the HomePage chats list.
And now the States.
And now the HomeBloc.
The HomeBloc creates a Stream from ChatRepository and whenever there are any updates, it triggers a ReceivedChatsEvent. This Event then yields FetchedHomeChatsState as the final state with data.
Retrieving the Data
Now comes probably the hardest part of today’s task - Retrieving the Conversation data from FireStore.
Conversation Model
Every conversation row will show/do few different things. Let’s see what they are:
- User details (name, profile pic) of the contact we’re chatting with.
- Latest message in the chat along with time of sending that message.
- And clicking it should open the Chat Page for that conversation (thus we’ll need the Chat ID).
Based on above info we can define our Conversation model as.
We’ll also need to add new factories to our User and Message Model.
Check Code Changes section for the complete changes in Message.dart
Modifying Database Structure
If you remember, the chats Collection schema for our DB looked something like this.
There’s one fundamental issue here. We have the latest message and the list of members. But the profile details(eg. name,profile pic) for the members are missing.You might think what’s the big deal? We can always read them from users Collection.
We definitely can but the read complexity in that case will be much higher. It will increase as the number of chats increase because for every chat we’ll have to,
- Take the user’s username.
- Get his UID from the username-uid map.
- Use that UID to retrieve the user details from
userscollection. - Repeat this for all the N chats.
To reduce this read complexity, we make a one time compromise on our write complexity. This technique of improving read speeds by duplicating data is called Fanning, in NOSQL Databases.
Lets update the ChatProvider.createChatIdForUsers method and introduce a new array called membersData.
Reading the Conversations as Stream
Here’s the getConversations method.
- It reads all the chats of which the current logged in user is a
memberof. - Sorts them based on latestMessage‘s
timestamp. - Maps the resulting documents to
List<Conversation>.
The Home Page UI
The HomePage UI has a SliverAppBar and SliverList with a GradientFab clicking which opens the ContactsPage.
Each individual row is a ChatRowWidget.
The BottomSheet on Chat Page
The BottomSheet on Chat Page uses the exact same logic but with a ListView.
And the end result looks pretty damn great I’d say!
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
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
- 60 Days Of Flutter : Building a Messenger from Scratch
- 60 Days of Flutter : Day 1 : Creating the App
- 60 Days of Flutter : Day 2 : Setting Up A CI With Flutter
- 60 Days of Flutter : Day 3–4 : Building a Chat Screen in Flutter
- 60 Days of Flutter : Day 4–5 : Widget Testing With Flutter
- 60 Days of Flutter : Day 6–7 : Implementing a Slideable Widget Using Bottomsheet in Flutter
- 60 Days of Flutter : Day 8 : Changing The Launcher Icon and Implementing GestureDetector
- 60 Days of Flutter : Day 9–10–11 : Creating Awesome Register Screen in Flutter
- 60 Days of Flutter : Day 12–14 : Understanding BLoC Pattern in Flutter
- 60 Days of Flutter : Day 15–17 : Implementing Registration Screen using ‘flutter_bloc’
- 60 Days of Flutter : Day 18–19 : Unit Testing in Flutter using ‘ mockito’
- 60 Days of Flutter : Day 20–21 : Unit Testing a Bloc in Flutter
- 60 Days of Flutter : Day 22–23 : Building a Modern Contacts Page in Flutter
- 60 Days of Flutter : Day 24–26 : Building a Animated Progress Fab and the Contacts Bloc in Flutter
- 60 Days of Flutter : Day 27–29 : Sending and Retrieving Messages from Firebase using BLOC
- 60 Days of Flutter : Day 30–32 : Firebase Chat UI using Stream and Bloc
- 60 Days of Flutter : Day 33–35 : Paginating data from Firestore using Firebase Queries
- 60 Days of Flutter : Day 36–38 : Seamlessly Upload Files to Firebase Storage
- 60 Days of Flutter : Day 39–41 : One UI Inspired Attachments Showcase Page
- 60 Days of Flutter : Day 42–45 : Creating the Home Page & Quick Peek BottomSheet for Messages
- 60 Days of Flutter : Day 45–47 : Adding Dark Mode to a Flutter App
- 60 Days of Flutter : Day 48–50 : Creating the Settings Page using Bloc
- 60 Days of Flutter : Day 51–54 : Unit Testing Firebase Providers with Mockito
- 60 Days of Flutter : Day 55–56 : Deploying Firestore Security Rules using Firebase CLI
- 60 Days of Flutter : Day 60 : Wrapping It Up
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!
