Crux is a Matrix client for iOS, built to get you to the most important messages as quick as possible.
It is built in native Swift and SwiftUI with the Matrix-Rust-SDK. It's core feature is the Mountain (better names welcome :)), a stack of cards, each for an unread conversation. These cards are then sorted into three piles: A "peak" pile with the most important messages, a "slope" pile with less important messages, and a muted pile with rooms set to "muted". Within these piles, cards are further sorted. All sorting is done using details about the room; this includes favorite status, low-priority status, mentions, if it is a DM, local AI with the Foundation Model Framework (will be opt-in), among other characteristics. Of course, all these parameters can be tuned in the settings. In addition to the "Mountain", you can access all rooms and spaces in their own tabs.
The goal of Crux is simple: Get it to be so quick at surfacing important messages that people don't have to spend a lot of time in the app. You should open the app and instantly see which important new messages, as defined by you, are there. All while simultaneously being a good Matrix client for participating in and creating new conversations.
Warning
Crux is not nearly feature complete, or even remotely stable yet. It is still in Alpha, if you can even call it that. A lot of what is described above is not yet complete, or there at all. Contributions are certainly welcome, but keep in mind the work in progress that this is! Thanks for giving this project a look!
In this project, I use a lot of other tools and projects that people have graciously open sourced. It is therefore extremely important to recognize and acknowledge what was used there, out of respect to them and often legal requirement 😀.
This project uses the MatrixRustSDK licensed under Apache 2.0. It is the only reason this is posssible, as it handles all of Matrix's very complicated sycning and cryptograpgy.
The method and code for the calling segment of the app was heavily inspired by the Relay client. It used a very cleaver way to provide a native MatrixRTC/Element Call implementation, and is the only reason I figured out how to do it here. Thanks!
[!INFO] This is not a complete (or necessarily up to date) explanation. I tried to make the code easy enough to read, so hopefully you can understand a lot of it easily if you wish, but this is just an overview. And, by the nature of a project still in development, this description is likely out of date already. I will try my best to keep it updated! Thank you!
Most of the views do not call anything in the SDK itself. There are "models" (RoomListModel, SpaceListModel, UserProfileModel, etc) that abstract the library for the views. The user session itself is represented by UserSession, accessible through the signed in state of the MatrixService. The session is stored (so it can be resumed when reopened) using the SessionStore, which stores the keys in the keychain and other information in the filesystem itself(in an app group so the NSE can access it).
RoomModel contains state about a specific room.
Spaces are organized similarly, with SpaceListModel representing the list of spaces. It contains SpaceNodes, which is one entry in a space (either a room or another space).
The messages in a room are represented by the TimelineModel.
There are a few more backed models that are self explanatory for the most part (MediaLoader for MXC, VerificationModel, UserProfileModel, etc). I try to keep this model architecture (sort of MVVM, not really though), but it is not perfectly consistent like that everywhere.
The files in Shared are shared between the different targets (currently just the iOS app and the Notification Service Extension). This is where the Clients are built, app configuration, session storage, etc. The NSE has some of its own code (since it has to decrypt the messages) in the CruxNSE folder.
Calls are handeled from the Call folder in Matrix. Crux uses the livekit SDK for the SFU logic itself, and uses the Matrix Rust SDK to manage state and get the keys it needs to feed to livekit.
You are more than welcome to use Generative Artificial Intelligence tools to contribute. I'll be honest, I used them to help create a decent amount of stuff in the app. The one thing that I please implore you to do, something that I also try and do: Read over any and all code generated by and it and make sure you understand and, crucially, agree with it before you try and submit anything. While modern AI tools are incredibly powerful, they are not perfect and often write unsaleable or messy code, full of lengthy and useless comments, often with UI that doesn't even make sense from a user's perspective. Moreover, as a human, you likely have a better sense of how an app should be designed. So please use AI as a tool not a replacement! Thank you!