Redesigning the room directory of Fractal

I have been working on the redesign of the room directory since I finished my first task. In this article, I will talk about the room directory (how it works and which improvements was needed), what I have done to improve it and some of the issues that are yet to be solved.

The initial issue

The previous room directory wasn’t very good regarding the user experience as it was just a big empty view with a search bar:


The layout of the room list wasn’t very nice either, especially when the width of the window was large:


Finally, you couldn’t search for rooms that wasn’t on your own homeserver.

So a new design was proposed to address these issues. Here is the design done by Tobias Bernard:


The issue was asking to have featured rooms displayed when entering the directory, to move the search entry to the header bar and change the layout of the room list (on the left part of the picture above). There was also a new server chooser that would work like this:

  • when “Default Server” is selected, the rooms searched are the ones from the user’s homeserver and the bridges (IRC, Gitter, Slack, etc…) of this server.
  • when “Specific Remote Server” is selected, the user put a URL in the URL bar under the radio button to specify an arbitrary homeserver to search on.

How the room directory works

How do we get into the directory view?

The application GUI is mainly divided in two parts (two `GtkStack`s): `headerbar_stack` and `main_content_stack`, each of these stacks are used for the different application’s states (the login/chat/directory states, for example) and deciding which of these states is displayed is done in this file. When you are in the chat view of the application, you click on the “+” button and then you click on the “Room directory” button in the popover, the application switches to the state `AppState::Directory` and the good `GtkBox`s are loaded for the `headerbar_stack` and `main_content_stack`.

How the room search works on the fractak-gtk end?

When you have the focus on the search entry and that you press enter (whether you’ve entered a query string or not), the function search_rooms is called: it gather the information for the search (the query string and the server you want to search on) and then sends a command to the backend to order it to fetch rooms. Then the backend loop catches the answer from the backend (that is a Vec<Room>) and calls the function `set_directory_rooms` that will add the received rooms to the room list on the GUI.

How the room search works on the fractal-api end?

When the backend receives the order to fetch rooms, it is done in the function room_search that takes the homeserver’s hostname we want to get the rooms from (it is the user’s homeserver when None is passed), the query string and the third party protocols fir which we also want to search rooms. The function then build the URL to make the request with the homeserver in the URL parameters and then make a JSON object that will precise the parameters of the query, such as the term search or the protocol and then all of this is send with a POST HTTP request (you can have more details about the request here). The term “protocol” in the sources are referencing the non-Matrix protocols that are bridged to a homeserver. We are making a request for the Matrix rooms and for each non-Matrix protocols (as you cannot ask for several third parties protocols in a single request). The answers contain a list of rooms. All the lists are then merged and sorted by their amount of members before being send into a backend response to the fractal-gtk crate.

How the development tasks was done

Adding featured rooms when there is no search term

It was quite simple as I just needed to tell to launch a search as soon as the application switches to the directory state, there is no search terms yet and when a homesever receives a query without search terms, it just returns the most popular rooms (i.e. with the most members). Here is the commit.

Moving search to the headerbar

For this one, I had some help from Christopher Davis (thank you again for this) that did a merge request on the branch I was working on, here is his commit.

Later, I remembered that there was a GtkListStore in the UI that was used to store the available protocols so that they could be selected in a GtkCombo list in order to search rooms from a specific non-Matrix protocol. But I’ve moved this into the AppOp struct because the GtkCombo didn’t exist anymore. Here is the commit.

Implementing a new server chooser popover

Next, I made the design of the server chooser popover using Glade. It took me a lot of time, especially because it was the first time I really used this application Here is the commit.

Implementing showing/searching rooms from arbitrary homeserver

I implemented the ability to search for rooms from arbitrary homeservers, by implementing it in the backend (in this commit) and then connecting the newly made server chooser popover with the rest of the application (more details here).

Later, I also implemented the ability to fetch rooms from the protocols bridged to the user’s homeserver (see here).

Implementing new room list layout

I had next to reimplement the room widget for the room list. As the widget is entirely coded here, I coded using gtk-rs this time (I didn’t used Glade). I had difficulties with the thumbnails of the room’s avatars because it was too small and not round (whereas it was required for the new design), so Daniel made a new image widget that I could use for this purpose by adding a small patch to be able to clip a circle in the avatar. You can see what was done for the new design of the room list layout here.

Final result

I will briefly show you the new design of the room directory. Here is the directory view:

Capture du 2018-05-29 23-27-50

And here is the server chooser popover:

Capture du 2018-05-29 23-29-27.png

The remaining issues

Implementation of the maximum column width

I couldn’t implement this because we first need a custom `GtkContainer` that keeps its child’s width under a percentage of the total space when the container’s size is under a certain width and the child’s width never exceeds a given fixed size when the container’s width is large.

The pagination of rooms from different protocols

For now, when we are searching rooms from several protocols at once, we have to make a request to the homeserver for each protocol. We then have a list of 20 rooms for each protocol, we merge all of these lists together and sort the resulting list by their number of members. But this naïve approach isn’t efficient at all, especially when it comes to request more rooms because we can discover rooms that should be earlier in the list we already have, for example. Furthermore, the search is very long because we are making too many requests. There are two possible options to solve this problem:

  • Find out a better algorithm to decide what requests to do in order to minimize the number of requests and at the same time preserve a total order in the rooms list.
  • Go back to what we were doing earlier: give the user the possibility to choose which protocol they want to search rooms from by adding a radio button in the server chooser popover and a combo list.

We will do more investigations for the upcoming weeks in order to address these issues.

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