60 Days of Flutter :Building a Messenger : Day 39–41 : One UI Inspired Attachments Showcase Page
In the last post we implemented uploading of attachments using Firestore. The user will also be able to access all the attachments which have been shared between him and a particular contact by clicking the Photos/Videos/Files buttons on the Chat Page.
We have three types of attachments right now.
- Photos
- Videos
- Files
All three will have their own separate tabs and the user will also be able to view/download them by clicking on them.
So let’s get started.
Retrieving the Attachments
First step would be to retrieve all the attachments from Firebase, filtered based on type.
Add the same method declarations to your BaseChatProvider.dart and ChatRepository.dart
Creating the Attachment Bloc
Create a new Bloc using bloc_code_generator under lib/blocs/attachments . You should have the following four files (I renamed them to remove the underscores).
This will contain our business logic. Refer this post to understand what a Bloc is and this post to understand how it’s implemented. Let’s define the States and the Events first.
We have just one Event which is the FetchAttachmentsEvent. It is triggered when the user visits any tab for the first time.
We have two states here.
- FetchedAttachmentsState: is yielded when the file type is
ImageorFile. - FetchedVideoState: is yielded when the file type is
Video. We have a separate State for video because while in case of the Image and File we can simply pass aListof their parent classMessagebut in case of Video we also need the thumbnail of theVideo. This thumbnail will be wrapped along using theVideoWrapperclass.
The AttachmentsBloc takes the events and maps them to states. This is how it looks.
The code here is pretty self explanatory. For videos we have added a extra step of fetching all the thumbnails in the el in a full screen preview. I have used Hero Animation here to make the transition look sleeker.se block and then wrapping them before yielding. For other file types we’re just yielding out the List of Message directly to the UI without any wrapper. SharedObjects.getThumbnail is a function which uses PlatformChannel. I’ll get back to it in the last part of the post.
Attachments Page
The AttachmentsPage follows the same One UI inspired design language we’ve been using throughout the app.
Here we have the usual UI stuff using the same SliverAppBar which we used for our Contacts Page.
- On Clicking any image, it is shown in a full screen preview. I used Hero Animation here to make the transition look sleeker.
- On Clicking a Video it’ll open in our
VideoPlayerWidgetwhich we created in the last post.
- The Files tab has a simple download button next to each file which triggers the download of file using flutter_downloader.
Everything to this point ran pretty smooth, except one thing. The Video Thumbnails. I started off with using video_thumbnail for loading the thumbnails. It seemed like a pretty straightforward thing and I included the package and created a helper function in our SharedObjects class like this.
But the problem was that it used PlatformChannel under the hood.
Platform Channel is a flutter API which let’s you write platform specific code and access it using Flutter.
And by default all PlatformChannel methods are invoked on the main thread. Quoting official docs.
Even though Flutter sends messages to and from Dart asynchronously, whenever you invoke a channel method, you must invoke that method on the platform’s main thread. See the section on threading for more information.
The creator of the package video_thumbnail probably didn’t notice but doing a heavy IO task like retrieving of thumbnails on the main thread is a bad bad idea. I have fixed the issue by writing my own implementation of it. Will probably submit a pull request to the package later for this fix or create my own.
So How to Create a Platform Channel?
Its pretty straightforward I’d say and the official docs explain it really well.
Create VideoThumbnail.dart under lib/utils. This will access our Platform Channel in dart.
Go to android/app/src/main/java and update your MainActivity.java file with the following code.
And now we have our Platform Channel ready. This was the last bit of fixing. Here’s the end result.
I also made minor changes to the the way the files were named on FireStore while saving so do checkout the Code Changes section for those minor fixes.
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
#25 Added attachment tabs and thumbnail loading for android
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!
