Improving Fractal’s media viewer

Fractal is a Matrix client for GNOME and is written in Rust. Matrix is an open network for secure, decentralized communication.

This week, I have made improvements for the media viewer. I will talk about the most important of them. You can have a look at this issue to get the full details of what has been done.

A header bar in the full screen mode

I’ve added the possibility to access the header bar while in full screen mode by moving the cursor up to the top of the screen, like in Builder or Videos.

At first, I didn’t have an idea of how I could implement it but I’ve figured out a way to simply do that.

First I’ve asked how it was done in the Builder IRC channel, someone told me to look at this page for implementing a custom header bar with full screen toggle button in Python. It could help me to figure out how to make the first step toward the implementation of this feature.

The media viewer UI has two main parts:

  • `media_viewer_headerbar_box` which is the part of the media viewer interface that goes in the `GtkStack` of the main window’s header bar
  • `media_viewer_box` which is the part of the media viewer interface that goes in the `GtkStack` of the main window’s content

When in full screen mode, we only see media_viewer_box on the entire screen, so in order to view the media viewer’s header bar, it needs to be moved in this GtkBox when entering in full screen mode and to be placed back in the header bar of the application when leaving this mode. The page I’ve previously cited helped me to know how to do that.

Doing this was far from being enough to get the expected result as I wanted the header bar to drop down when the cursor reaches the top of the screen. So I’ve added a GtkRevealer in the GtkOverlay containing the navigation buttons and the header bar would be placed into it instead of being directly added to media_viewer_box. The header bar would be revealed when the pointer is moved and when its vertical coordinate is less or equal than 6 pixels (i.e. when the cursor is close from the top of the screen). After that, a timer is set and when the time is out and that the cursor isn’t hovering the header bar, it is hidden back by the revealer.

I’ve finally hidden some buttons that could cause unexpected behaviors (the back and close buttons) when in full screen mode, the full screen button is also replaced by another one to leave the full screen mode.

Here are the MR for this and a picture of the result:

Capture du 2018-07-06 16-34-24

Add the possibility to go back in the media history without restrictions

Before this, the media viewer was navigating through a list of media which was built when we were entering the media viewer. Hence the navigation was limited to the media already present in the loaded messages.

To be able to go back beyond the available media, I needed to add a method in the backend that would fetch messages containing media from a certain message in the history (usually, the earliest media we currently have in the viewer). It is done by making a GET request to a homeserver at this address “/_matrix/client/r0/rooms/{roomId}/messages” with the query parameters “from” set with the previous batch ID, “dir” set to “b” (for backwards), “limit” set to 40 (that is the default page limit in Fractal), the user’s “access_token” and “filter” set to “{\”filter_json\”: { \”contains_url\”: true, \”not_types\”: [\”m.sticker\”] } }”. It says that we are requesting 40 messages having a “url” field and that are not of the type “m.sticker” (i.e. messages that contains media) starting from the previous batch (we will see later how to get it) and that we are going backward in the message history. The problem was to determine how to get the previous batch ID.

In Matrix, when a client is requesting a list of events, it does this by making a first request that asks for a certain number of them. When the server responds to this query, it sends a previous batch ID with it. It can be used by the client during the next request to ask for the next batch of events, and so on. The problem I had that I couldn’t use a message ID in order to ask for media after this message but I needed a previous batch ID if I wanted to start loading media from it, and I only have the message ID before doing the first request. So my mentor found out a way to get a previous batch ID from a message ID. This is done  by making a GET request to a homeserver at this address “/_matrix/client/r0/rooms/{roomId}/context/{eventId}” with the query parameter “limit” set to “0”. So the “start” field in the server’s answer is the previous batch ID associated with this event.

After the backend’s method was implemented (you can view the implementation in the commit here), it was then pretty much easy to integrate it within the media viewer (see this commit here). However, I needed to spend more time for the implementation of the loading spinner (it is needed when you press on the previous media button and that Fractal is fetching the images from a homeserver as this can take a while) because the UI was frozen while the backend was requesting more media from a server. So I’ve made the operation asynchronous (see this commit) and then I could add the spinner (see this commit).

You can see the full details on this MR.



4 thoughts on “Improving Fractal’s media viewer

    1. The media viewer is more a “preview” of the media and it better for the user experience than having to use other applications. Plus it is adding the possibility of navigating though the media of a room in chronological order. Fractal is starting to integrate GStreamer in order to have a preview of audio file and video (not implemented yet).
      Furthermore, if you open an image with EoG, you will end up navigating *all* the images in the cache (thumbnails, avatars, other rooms images) which isn’t great


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s