matrix-org / matrix-org/matrix-rust-sdk

timeline: always include a first virtual item

Open
#4,821 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

A-Timeline
Dominant language
Rust
Stars
2.3k
Forks
500
Avg merge
1d 16h
Merged PRs (30d)
106

Description

A room's timeline can be in three states:

- we know all the events
- we have a gap at the start of the timeline, and it is being resolved (via a pagination) right now
- we have a gap at the start of the timeline, and it is not being resolved right now

Historically, we've let embedders add UI items to signal that they've reached the start of the timeline or not. However, this creates complications, as the app have to look at the back-pagination status and conclude from there:

- lots of back-and-forths across the FFI layer to get this information
- the status is triggered async while back-paginated events will be inserted async too, so there can be latency between the time we know we reached the start of the timeline, and the time events will be inserted into the timeline. (Fun race condition: events being inserted *after* the app decided to show the start item)
- [nasty](https://github.com/element-hq/element-x-ios/issues/3768) bugs with [nasty](https://github.com/matrix-org/matrix-rust-sdk/pull/4818) [fixes](https://github.com/element-hq/element-x-ios/pull/3924)

https://github.com/matrix-org/matrix-rust-sdk/pull/4816 adds support for a virtual `TimelineStart` item, which is inserted after pagination terminates and we know we've hit the start of the timeline. This way, apps don't have to take care of it anymore.

The next steps would be to add another kind of virtual timeline item for gaps as well:

```rust
struct Gap {
/// Whether the gap is being resolved (via a back-pagination) now
resolving: bool,

/// The token used for pagination, if any.
token: Option,
}
```

The `token` field will serve to distinguish, in the future, gaps from one another, would we want to display gaps in general.

But even if we don't display gaps in general, we can improve the situation by maintaining the invariant that we always have a virtual timeline item at start:

- either the `TimelineStart` introduced in #4816,
- a `Gap { resolving: true }` if a back-pagination is ongoing
- a `Gap { resolving: false }` if there's a gap that might result in more events or hitting the timeline start

This may be used *also* in the context of the focused timeline, where a `Gap` could be inserted *at the bottom/end* (i.e. the most recent position) of the timeline, to indicate that there are more events to be forward-paginated.

## Rough plan

- [ ] #4816
- [ ] introduce the Gap virtual item
- [ ] live timeline: insert it at the right place, at the right time (and make sure there's either a gap or a timeline start as the first item)
- [ ] focused timeline: insert it for backward and forward paginations too

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reading #4816, which introduces the TimelineStart virtual item, then trace the live and focused timeline pagination paths described in the rough plan. Add the Gap virtual item and ensure the first item is always either a gap or TimelineStart, including backward and forward pagination in the focused timeline.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
backend
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.