diff --git a/crates/matrix-sdk-ui/src/timeline/pinned_events_loader.rs b/crates/matrix-sdk-ui/src/timeline/pinned_events_loader.rs index 002578c8b00..855de8fa533 100644 --- a/crates/matrix-sdk-ui/src/timeline/pinned_events_loader.rs +++ b/crates/matrix-sdk-ui/src/timeline/pinned_events_loader.rs @@ -51,6 +51,7 @@ impl PinnedEventsLoader { .rev() .collect(); + let has_pinned_event_ids = !pinned_event_ids.is_empty(); let mut loaded_events = Vec::new(); let mut event_ids_to_request = Vec::new(); for ev_id in pinned_event_ids { @@ -89,11 +90,15 @@ impl PinnedEventsLoader { for handle in handles { if let Ok(Ok(ev)) = handle.await { - loaded_events.push(ev) + loaded_events.push(ev); } } } + if has_pinned_event_ids && loaded_events.is_empty() { + return Err(PinnedEventsLoaderError::TimelineReloadFailed); + } + info!("Saving {} pinned events to the cache", loaded_events.len()); cache.set_bulk(&loaded_events).await; @@ -197,4 +202,7 @@ pub enum PinnedEventsLoaderError { #[error("Timeline focus is not pinned events.")] TimelineFocusNotPinnedEvents, + + #[error("Could not load pinned events.")] + TimelineReloadFailed, } diff --git a/crates/matrix-sdk-ui/tests/integration/timeline/pinned_event.rs b/crates/matrix-sdk-ui/tests/integration/timeline/pinned_event.rs index 0418488147a..16ce048d24e 100644 --- a/crates/matrix-sdk-ui/tests/integration/timeline/pinned_event.rs +++ b/crates/matrix-sdk-ui/tests/integration/timeline/pinned_event.rs @@ -166,21 +166,15 @@ async fn test_max_events_to_load_is_honored() { .await; let room = test_helper.client.get_room(&room_id).unwrap(); - let timeline = Timeline::builder(&room) + let ret = Timeline::builder(&room) .with_focus(TimelineFocus::PinnedEvents { max_events_to_load: 1 }) .build() - .await - .unwrap(); - - assert!( - timeline.live_back_pagination_status().await.is_none(), - "there should be no live back-pagination status for a focused timeline" - ); + .await; - let (items, mut timeline_stream) = timeline.subscribe().await; + // We're only taking the last event id, `$2`, and it's not available so the + // timeline fails to initialise. + assert!(ret.is_err()); - assert!(items.is_empty()); // We're only taking the last event id, `$2`, and it's not available - assert_pending!(timeline_stream); test_helper.server.reset().await; } @@ -256,15 +250,68 @@ async fn test_cached_events_are_kept_for_different_room_instances() { let room = test_helper.client.get_room(&room_id).unwrap(); // And a new timeline one - let timeline = Timeline::builder(&room) + let ret = Timeline::builder(&room) .with_focus(TimelineFocus::PinnedEvents { max_events_to_load: 2 }) .build() + .await; + + // Since the events are no longer in the cache the timeline couldn't load them + // and can't be initialised. + assert!(ret.is_err()); + + test_helper.server.reset().await; +} + +#[async_test] +async fn test_pinned_timeline_with_pinned_event_ids_and_empty_result_fails() { + let mut test_helper = TestHelper::new().await; + let room_id = test_helper.room_id.clone(); + + // Join the room + let _ = test_helper.setup_initial_sync_response().await; + test_helper.server.reset().await; + + // Load initial timeline items: a `m.room.pinned_events` with event $1 and $2 + // pinned, but they're not available neither in the cache nor in the HS + let _ = test_helper.setup_sync_response(Vec::new(), Some(vec!["$1", "$2"])).await; + + let room = test_helper.client.get_room(&room_id).unwrap(); + let ret = Timeline::builder(&room) + .with_focus(TimelineFocus::PinnedEvents { max_events_to_load: 1 }) + .build() + .await; + + // The timeline couldn't load any events so it fails to initialise + assert!(ret.is_err()); + + test_helper.server.reset().await; +} + +#[async_test] +async fn test_pinned_timeline_with_no_pinned_event_ids_is_just_empty() { + let mut test_helper = TestHelper::new().await; + let room_id = test_helper.room_id.clone(); + + // Join the room + let _ = test_helper.setup_initial_sync_response().await; + test_helper.server.reset().await; + + // Load initial timeline items: an empty `m.room.pinned_events` event + let _ = test_helper.setup_sync_response(Vec::new(), Some(Vec::new())).await; + + let room = test_helper.client.get_room(&room_id).unwrap(); + let timeline = Timeline::builder(&room) + .with_focus(TimelineFocus::PinnedEvents { max_events_to_load: 1 }) + .build() .await .unwrap(); + // The timeline couldn't load any events, but it expected none, so it just + // returns an empty list let (items, _) = timeline.subscribe().await; - assert!(items.is_empty()); // These events are no longer in the cache, so - // they couldn't be retrieved + assert!(items.is_empty()); + + test_helper.server.reset().await; } struct TestHelper {