Fractal is a popular Matrix chat client for the GNOME desktop which has been in development since 2017. Fractal was designed to work well for collaboration in large groups, such as free software projects. However, there are still two main areas where it would benefit from improvements: its performance and maintainability are limited, and it lacks some important features such as end-to-end encryption (E2EE).
Adding E2EE will increase the confidence that users have in the privacy of their conversations, making it nearly impossible for their conversations to be accessed by others. Because E2EE aims to prevent the service provider from being able to decrypt the messages, because the encryption keys are stored only on the end-user’s device. The direct consequence of this is that some work is delegated to the client. Some of this functionality is the same for each and every Matrix client, and includes technical components that could easily be implemented in the wrong way (especially the various encryption and security features). Most security researchers agree that redoing this work is a bad idea as it can lead to vulnerabilities. More generally, reimplementing the same functionality for each client doesn’t make much sense. On the other hand, sharing it with others allows projects that use it to contribute their expertise and polish it together instead of competing on a multitude of implementations. That shared work is called an SDK and could be considered the future “engine” of Fractal.
When Fractal was created, there was no existing code that we could rely on. We had to implement ourselves bits of the Matrix protocol in Fractal, at a low level. In the meantime, the Matrix Foundation has kickstarted matrix-rust-sdk, a library to channel the Matrix community efforts into a common, efficient library. This library, still in development for now, will allow us to drop a lot of our own code.
The current Fractal engine, which handles all the interactions with the servers, is entangled with the parts that handle the user interface. This severely impairs the evolutionary potential of Fractal and has a significant impact on performance. At first we attempted to untangle the user interface and engine. Alejandro worked at the same time on refactoring our messy code and porting it to the SDK, but it was just too much of a hassle and breakage kept happening. We weighed the pros and cons and ended up deciding that a rewrite was the better alternative. We will also use this opportunity to update Fractal to use a newer version of GTK, the toolkit which Fractal uses for its user interface, which brings many performance improvements. The rewrite we decided upon is a perfect opportunity to transition to GTK4 and design for it.
We launched the Fractal-next initiative to carry out all of this work: rebuild Fractal from scratch, with improved foundations. Those foundations are GTK4 for the User Interface code, and matrix-rust-sdk for the engine code. Fractal-next is only just acquiring basic functionality so is not ready for general testing yet.
Sharing the work with others
The ultimate goal for the matrix-rust-sdk is to be feature-complete. It means the SDK aims at providing an easy way for developers to interact with servers using every feature offered by the Matrix protocol.
The SDK is still in its early stages, but is already feature-rich enough to be useful. In particular, it already implements the end-to-end encryption features we need to support in Fractal. We want to contribute to it by implementing the features we want to rely on for Fractal, but which are not exclusive to Fractal.
A major part that the SDK is lacking is a high-level API: a description of what the engine can do and how to use it. This would allow developers without knowledge of the underlying technology to work with Matrix. This API would translate simple calls such as “send this message to this person” into the actual technical action compliant with the Matrix protocol. In the Matrix world, almost everything is an event that is sent to a Room, a conceptual place to send and receive events from. Someone sends a message to a room: that’s an event. Someone changes their display name: that’s an event. Someone is kicked: you got it, that’s an event.
I already started working on designing and improving the API. So far I wrote the code that developers will use to interact with Matrix rooms and their membership. I also have plans to do some thing similar with Matrix events, but the design requires more discussion.
I also added some convenience methods to the API. The SDK can now easily retrieve the avatar for users and for matrix rooms. Future improvements include optimising the process for retrieving the avatar and caching the image so that it doesn’t need to be re-downloaded every time it is needed. This and other optimizations will happen behind the scenes inside the SDK, without requiring the application developer to do anything.
Code is only one aspect of contributions: a lot of the actual work consists of providing feedback and discussions around improving the code. I started the conversation about how the SDK should store Matrix events. So far, the SDK mostly stores and cares about end-to-end encryption events. The final goal will be that the SDK stores most of information locally, this will be especially crucial for the search in encrypted rooms since it’s performed locally because the server doesn’t have access to the content of a conversation.
Progress so far
Rewriting Fractal from scratch is a huge undertaking, but it has to happen and we are on the right path. While the contributions to matrix-rust-sdk are important as it is foundational work for Fractal, I could start working on the application itself too.
Most of the boilerplate is set up. That is quite generic code, which is mostly the same for every GTK app. This includes the the folder and module structure we will use in Fractal’s codebase. Now that the core structure is in place we can incrementally implement each piece of Fractal untill we reach a feature rich Matrix client. If you run Fractal-next right now you will already see most of the UI even though it’s pretty much an empty shell.
I already implemented the login via password in Fractal-next, but there is no single sign on support yet. This was done on purpose because the login flow of Matrix is expected to change in the near future and the current login is enough to start making use of matrix-rust-sdk.
Furthermore, I spent significant time on finding a good approach to connect Fractal and the matrix-rust-sdk. They are both written in Rust but Fractal relies heavily on GTK and GLib . As a result, they use quite different paradigms. The interconnection of Fractal and matrix-rust-sdk needs to be carefully thought through to make use of their full potentials.
After logging in to Fractal-next, you can currently see the list of your rooms. The sidebar is mostly complete, but doesn’t contain room categories such as Favorites yet. I will add the base for this feature to the SDK before I can implement it in Fractal.
I will cover the code of the sidebar and the rest of the architecture of Fractal-next in much more detail in a future blogpost.
Milestones and next steps
So what is next on my TODO list? Well, as I previously mentioned, we have a list of rooms, but no interaction with the items in this list are possible, yet. So the next step will be to add the room history and allow switching between rooms from within the sidebar. Clicking on a room should bring up the history for the selected room. Once this is implemented, we will add the possibility to send messages. And by this point Fractal-next will be huge step closer to a client, but will still miss a lot before it can be considered a feature rich client for instant messaging.
I would like to thank NLnet for funding my work on Fractal and Fractal-next, to build a feature rich and polished client to make the instant messaging experience on Matrix as pleasant as possible. The funding of NlNet allows me to focus also on the SDK, so that other people will be able to build great software on top of the SDK and us the Matrix ecosystem.