From de65c94122bb2bb25ab8066b3ccacae9d4fd110d Mon Sep 17 00:00:00 2001 From: vaw Date: Sat, 11 Oct 2025 23:33:50 +0200 Subject: [PATCH] feat(timeline): Use read receipt as fallback for read marker Signed-off-by: vaw --- .../src/timeline/controller/mod.rs | 17 +++++++++++++---- .../src/timeline/controller/read_receipts.rs | 2 +- .../tests/integration/timeline/thread.rs | 10 ++++++++-- 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/crates/matrix-sdk-ui/src/timeline/controller/mod.rs b/crates/matrix-sdk-ui/src/timeline/controller/mod.rs index 1213c6c4d72..f999324b494 100644 --- a/crates/matrix-sdk-ui/src/timeline/controller/mod.rs +++ b/crates/matrix-sdk-ui/src/timeline/controller/mod.rs @@ -1012,11 +1012,20 @@ impl TimelineController

{ .await; } - if track_read_markers - && let Some(fully_read_event_id) = + if track_read_markers { + if let Some(fully_read_event_id) = self.room_data_provider.load_fully_read_marker().await - { - state.handle_fully_read_marker(fully_read_event_id); + { + state.handle_fully_read_marker(fully_read_event_id); + } else if let Some((last_read_event_id, _)) = state + .meta + .read_receipts + .get_latest(self.room_data_provider.own_user_id(), &ReceiptType::Read) + .cloned() + { + // Fall back to read receipt if no fully read marker exists. + state.handle_fully_read_marker(last_read_event_id); + } } } diff --git a/crates/matrix-sdk-ui/src/timeline/controller/read_receipts.rs b/crates/matrix-sdk-ui/src/timeline/controller/read_receipts.rs index 3af5b42323a..2de2e9eaff9 100644 --- a/crates/matrix-sdk-ui/src/timeline/controller/read_receipts.rs +++ b/crates/matrix-sdk-ui/src/timeline/controller/read_receipts.rs @@ -65,7 +65,7 @@ impl ReadReceipts { /// Read the latest read receipt of the given type for the given user, from /// the in-memory cache. - fn get_latest( + pub(crate) fn get_latest( &self, user_id: &UserId, receipt_type: &ReceiptType, diff --git a/crates/matrix-sdk-ui/tests/integration/timeline/thread.rs b/crates/matrix-sdk-ui/tests/integration/timeline/thread.rs index b538bbac759..072adda1b71 100644 --- a/crates/matrix-sdk-ui/tests/integration/timeline/thread.rs +++ b/crates/matrix-sdk-ui/tests/integration/timeline/thread.rs @@ -30,6 +30,7 @@ use matrix_sdk_test::{ }; use matrix_sdk_ui::timeline::{ RoomExt as _, TimelineBuilder, TimelineDetails, TimelineEventItemId, TimelineFocus, + VirtualTimelineItem, }; use ruma::{ MilliSecondsSinceUnixEpoch, @@ -1719,11 +1720,16 @@ async fn test_send_read_receipts() { assert_eq!(ev.event_id(), Some(event_id!("$2"))); assert!(ev.read_receipts().is_empty()); - let ev = initial_items[3].as_event().unwrap(); + // Since the room has no `m.fully_read` event, the read marker falls back to + // the normal read receipt. + let ev = initial_items[3].as_virtual().unwrap(); + assert!(matches!(ev, VirtualTimelineItem::ReadMarker)); + + let ev = initial_items[4].as_event().unwrap(); assert_eq!(ev.event_id(), Some(event_id!("$3"))); assert!(ev.read_receipts().is_empty()); - let ev = initial_items[4].as_event().unwrap(); + let ev = initial_items[5].as_event().unwrap(); assert_eq!(ev.event_id(), Some(event_id!("$4"))); let rr = ev.read_receipts(); assert_eq!(rr.len(), 1);