From 5a0c230a2d9b427640ff199bbe49323fa0249e4a Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Thu, 31 Aug 2023 10:31:44 +0200 Subject: [PATCH] feat(ui): `visible_rooms` can shrink its `timeline_limit`. This patch updates the behavior of `visible_rooms` where its `timeline_limit` is shrunk and expanded when the state machine is recovering. --- .../src/room_list_service/state.rs | 107 ++++++++++++++++-- .../tests/integration/room_list_service.rs | 26 ++++- 2 files changed, 124 insertions(+), 9 deletions(-) diff --git a/crates/matrix-sdk-ui/src/room_list_service/state.rs b/crates/matrix-sdk-ui/src/room_list_service/state.rs index b76f0bcce..63a5a3723 100644 --- a/crates/matrix-sdk-ui/src/room_list_service/state.rs +++ b/crates/matrix-sdk-ui/src/room_list_service/state.rs @@ -17,7 +17,10 @@ use std::future::ready; use async_trait::async_trait; -use matrix_sdk::{sliding_sync::Range, SlidingSync, SlidingSyncList, SlidingSyncMode}; +use matrix_sdk::{ + sliding_sync::{Bound, Range}, + SlidingSync, SlidingSyncList, SlidingSyncMode, +}; use once_cell::sync::Lazy; use ruma::events::StateEventType; @@ -61,9 +64,9 @@ impl State { let (next_state, actions) = match self { Init => (SettingUp, Actions::none()), - SettingUp => (Running, Actions::first_rooms_loaded()), + SettingUp => (Running, Actions::first_rooms_are_loaded()), - Recovering => (Running, Actions::recover_lists()), + Recovering => (Running, Actions::first_rooms_are_loaded_again()), Running => (Running, Actions::none()), @@ -77,7 +80,7 @@ impl State { } // If the previous state was `Running`, we enter the `Recovering` state. - Running => (Recovering, Actions::reset_lists()), + Running => (Recovering, Actions::prepare_to_load_first_rooms()), // Jump back to the previous state that led to this termination. state => (state.to_owned(), Actions::none()), @@ -101,6 +104,9 @@ trait Action { struct AddVisibleRoomsList; +/// Default timeline for the `VISIBLE_ROOMS_LIST_NAME` list. +pub const VISIBLE_ROOMS_DEFAULT_TIMELINE_LIMIT: Bound = 20; + /// Default range for the `VISIBLE_ROOMS_LIST_NAME` list. pub const VISIBLE_ROOMS_DEFAULT_RANGE: Range = 0..=19; @@ -113,7 +119,7 @@ impl Action for AddVisibleRoomsList { .sync_mode( SlidingSyncMode::new_selective().add_range(VISIBLE_ROOMS_DEFAULT_RANGE), ) - .timeline_limit(20) + .timeline_limit(VISIBLE_ROOMS_DEFAULT_TIMELINE_LIMIT) .required_state(vec![ (StateEventType::RoomEncryption, "".to_owned()), (StateEventType::RoomMember, "$LAZY".to_owned()), @@ -126,6 +132,42 @@ impl Action for AddVisibleRoomsList { } } +struct SetVisibleRoomsListToZeroTimelineLimit; + +#[async_trait] +impl Action for SetVisibleRoomsListToZeroTimelineLimit { + async fn run(&self, sliding_sync: &SlidingSync) -> Result<(), Error> { + sliding_sync + .on_list(VISIBLE_ROOMS_LIST_NAME, |list| { + list.set_timeline_limit(Some(0)); + + ready(()) + }) + .await + .ok_or_else(|| Error::UnknownList(VISIBLE_ROOMS_LIST_NAME.to_owned()))?; + + Ok(()) + } +} + +struct SetVisibleRoomsListToDefaultTimelineLimit; + +#[async_trait] +impl Action for SetVisibleRoomsListToDefaultTimelineLimit { + async fn run(&self, sliding_sync: &SlidingSync) -> Result<(), Error> { + sliding_sync + .on_list(VISIBLE_ROOMS_LIST_NAME, |list| { + list.set_timeline_limit(Some(VISIBLE_ROOMS_DEFAULT_TIMELINE_LIMIT)); + + ready(()) + }) + .await + .ok_or_else(|| Error::UnknownList(VISIBLE_ROOMS_LIST_NAME.to_owned()))?; + + Ok(()) + } +} + struct SetAllRoomsListToSelectiveSyncMode; /// Default `batch_size` for the selective sync-mode of the @@ -260,9 +302,9 @@ macro_rules! actions { impl Actions { actions! { none => [], - first_rooms_loaded => [SetAllRoomsListToGrowingSyncMode, SetInvitesListToGrowingSyncMode, AddVisibleRoomsList], - recover_lists => [SetAllRoomsListToGrowingSyncMode, SetInvitesListToGrowingSyncMode], - reset_lists => [SetAllRoomsListToSelectiveSyncMode, SetInvitesListToSelectiveSyncMode], + first_rooms_are_loaded => [SetAllRoomsListToGrowingSyncMode, SetInvitesListToGrowingSyncMode, AddVisibleRoomsList], + first_rooms_are_loaded_again => [SetAllRoomsListToGrowingSyncMode, SetInvitesListToGrowingSyncMode, SetVisibleRoomsListToDefaultTimelineLimit], + prepare_to_load_first_rooms => [SetAllRoomsListToSelectiveSyncMode, SetInvitesListToSelectiveSyncMode, SetVisibleRoomsListToZeroTimelineLimit], } fn iter(&self) -> &[OneAction] { @@ -399,6 +441,55 @@ mod tests { Ok(()) } + #[async_test] + async fn test_action_set_visible_rooms_list_to_zero_or_default_timeline_limit( + ) -> Result<(), Error> { + let room_list = new_room_list().await?; + let sliding_sync = room_list.sliding_sync(); + + // List is absent. + assert_eq!(sliding_sync.on_list(VISIBLE_ROOMS_LIST_NAME, |_list| ready(())).await, None); + + // Run the action! + AddVisibleRoomsList.run(sliding_sync).await?; + + // List is present, and has the default `timeline_limit`. + assert_eq!( + sliding_sync + .on_list(VISIBLE_ROOMS_LIST_NAME, |list| ready( + list.timeline_limit() == Some(VISIBLE_ROOMS_DEFAULT_TIMELINE_LIMIT) + )) + .await, + Some(true) + ); + + // Run the action! + SetVisibleRoomsListToZeroTimelineLimit.run(sliding_sync).await?; + + // List is present, and has a zero `timeline_limit`. + assert_eq!( + sliding_sync + .on_list(VISIBLE_ROOMS_LIST_NAME, |list| ready(list.timeline_limit() == Some(0))) + .await, + Some(true) + ); + + // Run the action! + SetVisibleRoomsListToDefaultTimelineLimit.run(sliding_sync).await?; + + // List is present, and has the default `timeline_limit`. + assert_eq!( + sliding_sync + .on_list(VISIBLE_ROOMS_LIST_NAME, |list| ready( + list.timeline_limit() == Some(VISIBLE_ROOMS_DEFAULT_TIMELINE_LIMIT) + )) + .await, + Some(true) + ); + + Ok(()) + } + #[async_test] async fn test_action_set_all_rooms_list_to_growing_and_selective_sync_mode() -> Result<(), Error> { diff --git a/crates/matrix-sdk-ui/tests/integration/room_list_service.rs b/crates/matrix-sdk-ui/tests/integration/room_list_service.rs index 85754a1c2..2c5b2bea9 100644 --- a/crates/matrix-sdk-ui/tests/integration/room_list_service.rs +++ b/crates/matrix-sdk-ui/tests/integration/room_list_service.rs @@ -687,6 +687,7 @@ async fn test_sync_resumes_from_error() -> Result<(), Error> { VISIBLE_ROOMS: { // Hello new list. "ranges": [[0, 19]], + "timeline_limit": 20, }, INVITES: { // The sync-mode has changed to growing, with its initial range. @@ -722,6 +723,8 @@ async fn test_sync_resumes_from_error() -> Result<(), Error> { VISIBLE_ROOMS: { // We have set a viewport, which reflects here. "ranges": [[5, 10]], + // The `timeline_limit` has been set to zero. + "timeline_limit": 0, }, INVITES: { // Due to previous error, the sync-mode is back to selective, with its initial range. @@ -755,6 +758,8 @@ async fn test_sync_resumes_from_error() -> Result<(), Error> { VISIBLE_ROOMS: { // Viewport hasn't changed. "ranges": [[5, 10]], + // The `timeline_limit` has been restored. + "timeline_limit": 20, }, INVITES: { // Sync-mode is now growing. @@ -789,6 +794,7 @@ async fn test_sync_resumes_from_error() -> Result<(), Error> { VISIBLE_ROOMS: { // The range is kept. "ranges": [[5, 10]], + // `timeline_limit` is a sticky parameter, so it's absent now. }, INVITES: { // The sync-mode is still growing, and the range has made progress. @@ -821,6 +827,8 @@ async fn test_sync_resumes_from_error() -> Result<(), Error> { VISIBLE_ROOMS: { // We have set a viewport, which reflects here. "ranges": [[5, 10]], + // The `timeline_limit` has been set to 0. + "timeline_limit": 0, }, INVITES: { // Due to previous error, the range has been reset. @@ -854,6 +862,8 @@ async fn test_sync_resumes_from_error() -> Result<(), Error> { VISIBLE_ROOMS: { // Viewport hasn't changed. "ranges": [[5, 10]], + // The `timeline_limit` has been restored. + "timeline_limit": 20, }, INVITES: { // The sync-mode is now growing, and has reached its maximum. @@ -887,6 +897,7 @@ async fn test_sync_resumes_from_error() -> Result<(), Error> { VISIBLE_ROOMS: { // No error. The range is still here. "ranges": [[5, 10]], + // `timeline_limit` is a sticky parameter, so it's absent now. }, INVITES: { // The range has reached its maximum. @@ -922,6 +933,7 @@ async fn test_sync_resumes_from_error() -> Result<(), Error> { VISIBLE_ROOMS: { // The range is still here. "ranges": [[5, 10]], + // `timeline_limit` is a sticky parameter, so it's absent now. }, INVITES: { // The range has reached a new maximum. @@ -954,6 +966,8 @@ async fn test_sync_resumes_from_error() -> Result<(), Error> { VISIBLE_ROOMS: { // We have set a viewport, which reflects here. "ranges": [[5, 10]], + // The `timeline_limit` has been set to 0. + "timeline_limit": 0, }, INVITES: { // Due to previous error, the range is back to selective, with its initial range. @@ -987,6 +1001,8 @@ async fn test_sync_resumes_from_error() -> Result<(), Error> { VISIBLE_ROOMS: { // Viewport hasn't changed. "ranges": [[5, 10]], + // The `timeline_limit` has been restored. + "timeline_limit": 20, }, INVITES: { // Sync-mode is now growing, and has reached its maximum. @@ -1070,6 +1086,8 @@ async fn test_sync_resumes_from_terminated() -> Result<(), Error> { VISIBLE_ROOMS: { // Hello new list. "ranges": [[0, 19]], + // `timeline_limit` has been set to zero. + "timeline_limit": 0, }, INVITES: { // The sync-mode is still selective, with its initial range. @@ -1102,8 +1120,9 @@ async fn test_sync_resumes_from_terminated() -> Result<(), Error> { "ranges": [[0, 99]], }, VISIBLE_ROOMS: { - // Hello new list. "ranges": [[0, 19]], + // `timeline_limit` has been restored. + "timeline_limit": 20, }, INVITES: { // The sync-mode is now growing, with its initial range. @@ -1149,6 +1168,8 @@ async fn test_sync_resumes_from_terminated() -> Result<(), Error> { VISIBLE_ROOMS: { // We have set a viewport, which reflects here. "ranges": [[5, 10]], + // `timeline_limit` has been set to zero. + "timeline_limit": 0, }, INVITES: { // The sync-mode is back to selective.. @@ -1183,6 +1204,8 @@ async fn test_sync_resumes_from_terminated() -> Result<(), Error> { VISIBLE_ROOMS: { // We have set a viewport, which reflects here. "ranges": [[5, 10]], + // `timeline_limit` has been restored. + "timeline_limit": 20, }, INVITES: { // Sync-mode is growing, and has reached its maximum. @@ -1217,6 +1240,7 @@ async fn test_sync_resumes_from_terminated() -> Result<(), Error> { VISIBLE_ROOMS: { // We have set a viewport, which reflects here. "ranges": [[5, 10]], + // `timeline_limit` is a sticky parameter, so it's absent now. }, INVITES: { // Range has reached its maximum.