Skip to main content

3 posts tagged with "guide"

View All Tags

· 2 min read
Nigel Maynard

Background

I chose Bloc as the state management solution for Quiri after a lot of reading into the different options because I felt that it had less "magic". It also had twice the Github stars of the next most popular project and seemed to have the support of larger teams. Since choosing it there have been some challenges.

  • side-effects and one-time events like page navigations and toast messages
  • streaming data from the matrix client

Streaming from the Matrix Client

I go into more detail on how the matrix Dart SDK syncs data with the server and exposes in the [Listening for New Messages With the Matrix SDK](2024-12-19-listening-for-new-messages-with-the-matrix-sdk copy.md) article. Ultimately the SDK already maintains the state of all events, etc. that come from the Matrix server. What the SDK exposes to Bloc then is a state object and a collection of streams that can be subsciribed to that provide all event details. I have been subscribing to the matrix streams in the Bloc and then adding events to the bloc for each new emission from the matrix stream. This article from the Bloc team presents emit.forEach as an option for subscribing to reactive repositories instead. They show the same pattern here in the docs.

· 2 min read
Nigel Maynard

Background

Almost all actions in matrix are expressed as users sending events to rooms. This makes intuitive sense when it comes to message events but works equally well for non-message events (e.g. add user event, change room name event, etc). When a user adds an event to a room, it is first added to the event graph on their personal client, then it is replicated to the user's home server and then it is replicated to all other clients that are in that room. Quiri is written in Dart and uses the matrix dart sdk to handle a lot of the client-server relationship. This includes maintaining the local copy of the current state of a room's state and listening for updates to that room's state. This guide goes into details about how that relationship is maintained so that we can build the quiri client appropriately.

Listening for events

On app startup, we currently call the init method. This method does a number of things including kicking off the first _sync request.

This sync call can be awaited as a whole, or you can provide the waitForFirstSync as false and instead await the roomsLoading, _accountDataLoading and userDeviceKeysLoading futures individually. We will await on the init for now for simplicity.

After the initial sync, the client will begin a _backgroundSync that long polls every 30 seconds (configurable).

Replicating the state in the client

Each sync job uses the _handleSync method to perform the appropriate updates to state.

For example, in the _handleRoomEvents sub-handler the updates are made in the following order:

  • the in-memory state (accessible from the SDK client object e.g. client.rooms)
  • the client side database for persistent storage
  • the SDK's exposed event streams

Reacting to new events in the UI

In particular, how do we know when new messages have arrived? Let's look at how Fluffychat does it. First let's look at where they render their chat boxes. The messages are found in a room's timeline. The timeline is returned from the SDK getTimeline method. An onUpdate callback is passed to allow the UI to react to new messages arriving. Here is where Fluffychat sets up the timeline listener for new messages

· 2 min read
Nigel Maynard

Background

Inviting someone to a Quiri is a core experience in the quiri app. This guide studies the matrix invite functionality as well as how the Dart SDK implements it (with references to how Fluffychat does it.) See User Discovery in Quiri for a discussion of user discoverability and maintaining a contact list.

Accepting an Invite

Lets see how Fluffychat does it. It appears that when you are invited to a room, you will be added to the room but with a membership status of invite. The SDK calls the join room endpoint. Fluffychat is then SDK's client.waitForRoomInSync method to wait for that room to be enabled after the room join event is added to the event graph.

TODO:

  • how do you list rooms that you have been invited to?

Listening for Invites

The SDK offers the waitForRoomInSync method that waits for a specific room by ID to experience an invite, join or leave event. For private rooms I don't imagine that you would know the id of the room to be able to listen for it in this way. I haven't figured out how Fluffychat handles room invites but based on the waitForRoomInSync method I am watching the onSync stream, filtering on room events.