diff --git a/Cargo.lock b/Cargo.lock index 9817cbec1..8da0f6533 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -323,6 +323,12 @@ dependencies = [ "event-listener", ] +[[package]] +name = "async-once-cell" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fddec5f567375e0a634f94bc8dab1059b9d59a8aba12134c32f5ee21ce3f5f89" + [[package]] name = "async-process" version = "1.7.0" @@ -2939,6 +2945,7 @@ dependencies = [ "anyhow", "assert-json-diff", "assert_matches", + "async-once-cell", "async-stream", "async-trait", "chrono", diff --git a/crates/matrix-sdk-ui/Cargo.toml b/crates/matrix-sdk-ui/Cargo.toml index d59898240..0026107d5 100644 --- a/crates/matrix-sdk-ui/Cargo.toml +++ b/crates/matrix-sdk-ui/Cargo.toml @@ -17,6 +17,7 @@ experimental-sliding-sync = ["matrix-sdk/experimental-sliding-sync"] testing = ["matrix-sdk/testing"] [dependencies] +async-once-cell = "0.5.2" async-stream = { workspace = true, optional = true } async-trait = { workspace = true } chrono = "0.4.23" diff --git a/crates/matrix-sdk-ui/src/room_list/mod.rs b/crates/matrix-sdk-ui/src/room_list/mod.rs index 54bf4d58c..c6af05cb0 100644 --- a/crates/matrix-sdk-ui/src/room_list/mod.rs +++ b/crates/matrix-sdk-ui/src/room_list/mod.rs @@ -62,6 +62,7 @@ use std::{future::ready, sync::Arc}; +use async_once_cell::OnceCell as AsyncOnceCell; use async_stream::stream; use async_trait::async_trait; use eyeball::shared::Observable; @@ -270,11 +271,11 @@ struct RoomInner { room: matrix_sdk::room::Room, /// The timeline of the room. - timeline: Timeline, + timeline: AsyncOnceCell, /// The “sneaky” timeline of the room, i.e. this timeline doesn't track the /// read marker nor the receipts. - sneaky_timeline: Timeline, + sneaky_timeline: AsyncOnceCell, } impl Room { @@ -285,19 +286,13 @@ impl Room { .get_room(sliding_sync_room.room_id()) .ok_or_else(|| Error::RoomNotFound(sliding_sync_room.room_id().to_owned()))?; - let timeline = Timeline::builder(&room) - .events(sliding_sync_room.prev_batch(), sliding_sync_room.timeline_queue()) - .track_read_marker_and_receipts() - .build() - .await; - - let sneaky_timeline = Timeline::builder(&room) - .events(sliding_sync_room.prev_batch(), sliding_sync_room.timeline_queue()) - .build() - .await; - Ok(Self { - inner: Arc::new(RoomInner { sliding_sync_room, room, timeline, sneaky_timeline }), + inner: Arc::new(RoomInner { + sliding_sync_room, + room, + timeline: AsyncOnceCell::new(), + sneaky_timeline: AsyncOnceCell::new(), + }), }) } @@ -313,8 +308,20 @@ impl Room { } /// Get the timeline of the room. - pub fn timeline(&self) -> &Timeline { - &self.inner.timeline + pub async fn timeline(&self) -> &Timeline { + self.inner + .timeline + .get_or_init(async { + Timeline::builder(&self.inner.room) + .events( + self.inner.sliding_sync_room.prev_batch(), + self.inner.sliding_sync_room.timeline_queue(), + ) + .track_read_marker_and_receipts() + .build() + .await + }) + .await } /// Get the latest event of the timeline. @@ -322,7 +329,20 @@ impl Room { /// It's different from `Self::timeline().latest_event()` as it won't track /// the read marker and receipts. pub async fn latest_event(&self) -> Option { - self.inner.sneaky_timeline.latest_event().await + self.inner + .sneaky_timeline + .get_or_init(async { + Timeline::builder(&self.inner.room) + .events( + self.inner.sliding_sync_room.prev_batch(), + self.inner.sliding_sync_room.timeline_queue(), + ) + .build() + .await + }) + .await + .latest_event() + .await } } diff --git a/crates/matrix-sdk-ui/tests/integration/room_list.rs b/crates/matrix-sdk-ui/tests/integration/room_list.rs index 16738f654..0df54c5fe 100644 --- a/crates/matrix-sdk-ui/tests/integration/room_list.rs +++ b/crates/matrix-sdk-ui/tests/integration/room_list.rs @@ -1166,7 +1166,7 @@ async fn test_room_timeline() -> Result<(), Error> { }; let room = room_list.room(room_id).await?; - let timeline = room.timeline(); + let timeline = room.timeline().await; let (previous_timeline_items, mut timeline_items_stream) = timeline.subscribe().await;