The timeline already listens to changes to the pinned events list (via a
stream), so there's no need to fully reload all the pinned events every
time we receive a new event that's pinned. Technically it may avoid one
or a few lookups, but this is cheap and a subsequent commit/PR will
merge the pinned event cache into the event cache.
It's better to have fewer public APIs, especially when there's little
annoyance to have it. We could use a request builder that converts into
a Future, too, but considering there's only a single optional parameter,
it's fine to include it in the function's signature.
We should only show the spinner if the *first* sliding sync request is
taking a while. If we have received some data and the second request
takes a while, that is OK.
For the state transition of `Init -> SettingUp` this is handled
correctly, however for `Terminated -> Recovering -> Running` we waited
until the second request returned before hiding the sync spinner. This
meant that if the first request returned quickly the app would show new
data and *then* the sync spinner would show (if the second request took
time).
This situation occurs frequently with the new SSS API, where if all the
new data was returned in the first sync then the second sync would
block waiting for new data, triggering the sync spinner.
This patch changes the `SlidingSync::subscribe_to_room` method to
`subscribe_to_rooms`. Note the plural form. It's now mandatory to
subscribe to a set of rooms. The idea is to avoid calling this method
repeatedly. Why? Because each time the method is called, it sends a
`SlidingSyncInternalMessage` of kind `SyncLoopSkipOverCurrentIteration`,
i.e. it cancels the in-flight sliding sync request, to start over with
a new one (with the new room subscription). A problem arises when the
async runtime (here, Tokio) is busy: in this case, the internal message
channel can be filled pretty easily because its size is 8. Messages
are not consumed as fast as they are inserted. By changing this API:
subscribing to multiple rooms will result in a single internal message,
instead of one per room.
Consequently, the rest of the patch moves the `subscribe` method of
`room_list_service::Room` to `room_list_service::RoomListService`
because it now concerns multiple rooms instead of a single one.
This method works the same as `Room::event` but you can provide a custom `RequestConfig` to it.
It's especially useful for the pinned events timeline, since we need a max number of retries and a max number of concurrent requests. With this we can remove some unnecessary complexity.
This way it matches the rest of timelines in the SDK, I reversed it here because I didn't realise most clients just do this reversal of ordering themselves. As they do, they need the same order for this timeline too to be able to reuse their existing logic.
Add `PinnedEventsLoader` to encapsulate this logic, being able to provide a max number of events to load and how many can be loaded at the same time. Also implement an event cache for it.
Add `PinnedEventsRoom` trait to use it in the same way as `PaginableRoom`, only for pinned events.
This tiny change allows one to easily name the return type of
`EventTimelineItem::reactions()` such that you can use it in a function
signature. Same goes for the `ReactionInfo` type.
I think this was likely just a small oversight in recent changes to the
reactions API, so hopefully it's not controversial.
Without this, it's impossible to write a function that uses
`ReactionsByKeyBySender` or `ReactionInfo` in the signature.
Signed-off-by: Kevin Boos <kevinaboos@gmail.com>
This makes it impossible to represent states like "there's a local *and*
a remote echo for the same sender for a given reaction", or multiple
reactions from the same sender to the same event, and so on.