project-robius / robrix

A Matrix chat client written in pure Rust using the Makepad UI toolkit and the Robius app dev framework
MIT License
67 stars 11 forks source link

Automatically paginate timeline based on scroll position/movement #109

Open kevinaboos opened 3 weeks ago

kevinaboos commented 3 weeks ago

Pagination refers to requesting older (or newer) messages from the server to fill in missing messages in a room's timeline.

Current vs. Expected Behavior

Currently, a room's timeline is only paginated each time the room is opened (clicked on) from the main rooms list screen. This is obviously not the best way to do things and was just a temporary test of pagination functionality.

Instead, pagination should be done automatically/dynamically based on the scroll position of the timeline.

The most typical case of this is when scrolling up (backwards through timeline history to older messages). A pagination request should be made when all of the following are true:

  1. the start of the timeline has not yet been reached (when TimelineUiState::fully_paginated is false)
  2. The user is scrolling upwards
  3. The timeline PortalList's first_id is a low number, i.e., close to zero.
    • It may take some experimentation to determine at which item index/ID a pagination request should be made (e.g., should it be submitted when we scroll up to ID 5? or ID 1? or should it be based on scrolling speed?)

Note: There is also another case of scrolling down when the timeline was focused on a specific event that is older than the most recent messages. There is not yet any infrastructure to support focused mode in Robrix, as it was just recently added to the Matrix SDK itself. So our first priority should be handling backwards pagination only.

UI behavior

While waiting for the pagination response to arrive from the server, we should show a "loading spinner" animation that indicates to the user that pagination is underway and waiting for a response. Currently Makepad doesn't have a built-in "loading spinner" widget, so we can just use the existing design of showing a simple message at the top that says "Loading...".

I have already accounted for this in the timeline UI design, at least for the backwards pagination case, by adding in a UI element called TopSpace at the top of the timeline, which is always item index 0. See here: https://github.com/project-robius/robrix/blob/106033de803df72e7242267c147792cdee8a8878/src/home/room_screen.rs#L1188

By default, the TopSpace has a height of 0, meaning it's not rendered. As part of addressing this issue, its height should be set to Fit and its visibility should be set to true after a pagination request is submitted, and then its visibility should be sett o false after pagination has completed (as well as any other time that pagination is not happening). Search for "TopSpace" in the room_screen.rs file to see other places where it is used.

Then, when pagination completes, the TopSpace should be hidden here: https://github.com/project-robius/robrix/blob/106033de803df72e7242267c147792cdee8a8878/src/home/room_screen.rs#L1150-L1153

Later, when we support forwards pagination as well, we can add a similar BottomSpace UI element that works just like TopSpace, but only for forwards pagination requests. This will likely only be used when the timeline is in focused mode (i.e., it is focused on a specific older message rather than showing the latest messages in "Live" mode).