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 Image or File .

is yielded when the file type is or . 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 a List of their parent class Message but in case of Video we also need the thumbnail of the Video . This thumbnail will be wrapped along using the VideoWrapper class.

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 VideoPlayerWidget which 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

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!