feat(ui): Make Room::timeline and ::sneaky_timeline lazy.

This patch uses a new `async-once-cell` crate to make `Room::timeline`
and `Room::sneaky_timeline` by making them lazy. Their values are
computed lazily, on-demand, when calling the `Room::timeline` method or
`Room::latest_event`.
This commit is contained in:
Ivan Enderlin
2023-06-07 09:51:56 +02:00
parent 169038504d
commit 3acb56aa31
4 changed files with 46 additions and 18 deletions

7
Cargo.lock generated
View File

@@ -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",

View File

@@ -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"

View File

@@ -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<Timeline>,
/// 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<Timeline>,
}
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<EventTimelineItem> {
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
}
}

View File

@@ -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;