diff --git a/crates/matrix-sdk-ui/src/room_list/mod.rs b/crates/matrix-sdk-ui/src/room_list/mod.rs index 2843b0b5a..40a94e003 100644 --- a/crates/matrix-sdk-ui/src/room_list/mod.rs +++ b/crates/matrix-sdk-ui/src/room_list/mod.rs @@ -1,17 +1,13 @@ //! `RoomList` API. -use std::{ - fmt, - future::ready, - sync::{Arc, Mutex, RwLock, RwLockWriteGuard}, -}; +use std::future::ready; use async_stream::stream; use async_trait::async_trait; use eyeball::shared::Observable; use eyeball_im::VectorDiff; -use eyeball_im_util::FilteredVectorSubscriber; use futures_util::{pin_mut, Stream, StreamExt}; +use imbl::Vector; pub use matrix_sdk::RoomListEntry; use matrix_sdk::{ Client, Error as SlidingSyncError, SlidingSync, SlidingSyncList, SlidingSyncMode, @@ -22,43 +18,20 @@ use thiserror::Error; pub const ALL_ROOMS_LIST_NAME: &str = "all_rooms"; pub const VISIBLE_ROOMS_LIST_NAME: &str = "visible_rooms"; +#[derive(Debug)] pub struct RoomList { sliding_sync: SlidingSync, - entries_stream: RwLock< - FilteredVectorSubscriber bool + Sync + Send>>, - >, state: Observable, } -impl fmt::Debug for RoomList { - fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { - formatter - .debug_struct("RoomList") - .field("sliding_sync", &self.sliding_sync) - .field("state", &self.state) - .finish_non_exhaustive() - } -} - impl RoomList { pub async fn new(client: Client) -> Result { - let entries = Arc::new(Mutex::new(None)); let sliding_sync = client .sliding_sync() .storage_key(Some("matrix-sdk-ui-roomlist".to_string())) .add_cached_list( SlidingSyncList::builder(ALL_ROOMS_LIST_NAME) - .sync_mode(SlidingSyncMode::new_selective().add_range(0..=19)) - .once_built({ - let entries = entries.clone(); - - move |list| { - *entries.lock().unwrap() = - Some(list.room_list_filtered_stream(Box::new(|_| true))); - - list - } - }), + .sync_mode(SlidingSyncMode::new_selective().add_range(0..=19)), ) .await .map_err(Error::SlidingSync)? @@ -66,14 +39,7 @@ impl RoomList { .await .map_err(Error::SlidingSync)?; - let entries = - Arc::try_unwrap(entries).map_err(|_| Error::Entries)?.into_inner().unwrap().unwrap(); - - Ok(Self { - sliding_sync, - entries_stream: RwLock::new(entries), - state: Observable::new(State::Init), - }) + Ok(Self { sliding_sync, state: Observable::new(State::Init) }) } pub fn sync(&self) -> impl Stream> + '_ { @@ -127,26 +93,23 @@ impl RoomList { Observable::subscribe(&self.state) } - pub fn entries_stream( + pub async fn entries( &self, - ) -> RwLockWriteGuard>> { - self.entries_stream.write().unwrap() + ) -> Result<(Vector, impl Stream>), Error> { + self.sliding_sync + .on_list(ALL_ROOMS_LIST_NAME, |list| ready(list.room_list_stream())) + .await + .ok_or_else(|| Error::UnknownList(ALL_ROOMS_LIST_NAME.to_string())) } - pub async fn update_entries_stream_filter( + pub async fn entries_filtered( &self, - filter: Box bool + Sync + Send>, - ) -> Result<(), Error> { - let mut entries_stream = - self.entries_stream.try_write().map_err(|_| Error::CannotUpdateEntriesFilter)?; - - *entries_stream = self - .sliding_sync + filter: impl Fn(&RoomListEntry) -> bool + Send + Sync + 'static, + ) -> Result<(Vector, impl Stream>), Error> { + self.sliding_sync .on_list(ALL_ROOMS_LIST_NAME, |list| ready(list.room_list_filtered_stream(filter))) .await - .ok_or_else(|| Error::UnknownList(ALL_ROOMS_LIST_NAME.to_string()))?; - - Ok(()) + .ok_or_else(|| Error::UnknownList(ALL_ROOMS_LIST_NAME.to_string())) } #[cfg(any(test, feature = "testing"))] diff --git a/crates/matrix-sdk-ui/tests/integration/room_list.rs b/crates/matrix-sdk-ui/tests/integration/room_list.rs index 88b2dd294..5347f4392 100644 --- a/crates/matrix-sdk-ui/tests/integration/room_list.rs +++ b/crates/matrix-sdk-ui/tests/integration/room_list.rs @@ -646,12 +646,12 @@ async fn test_entries_stream_with_updated_filter() -> Result<(), Error> { // Second, update the filter. room_list - .update_entries_stream_filter(Box::new(|room_list_entry| { + .update_entries_stream_filter(|room_list_entry| { matches!( room_list_entry.as_room_id(), Some(room_id) if room_id.server_name() == "bar.org" ) - })) + }) .await?; // Third, let's get a new entries stream. diff --git a/crates/matrix-sdk/src/sliding_sync/list/mod.rs b/crates/matrix-sdk/src/sliding_sync/list/mod.rs index 48399429d..4d99277f7 100644 --- a/crates/matrix-sdk/src/sliding_sync/list/mod.rs +++ b/crates/matrix-sdk/src/sliding_sync/list/mod.rs @@ -17,6 +17,7 @@ use eyeball_im::{ObservableVector, VectorDiff}; use eyeball_im_util::{FilteredVectorSubscriber, VectorExt}; pub(super) use frozen::FrozenSlidingSyncList; use futures_core::Stream; +use imbl::Vector; pub(super) use request_generator::*; pub use room_list_entry::RoomListEntry; use ruma::{api::client::sync::sync_events::v4, assign, events::StateEventType, OwnedRoomId}; @@ -49,6 +50,8 @@ pub struct SlidingSyncList { inner: Arc, } +type BoxedRoomListEntryFilter = Box bool + Sync + Send>; + impl SlidingSyncList { /// Create a new [`SlidingSyncListBuilder`] with the given name. pub fn builder(name: impl Into) -> SlidingSyncListBuilder { @@ -125,8 +128,13 @@ impl SlidingSyncList { /// /// There's no guarantee of ordering between items emitted by this stream /// and those emitted by other streams exposed on this structure. - pub fn room_list_stream(&self) -> impl Stream> { - ObservableVector::subscribe(&self.inner.room_list.read().unwrap()) + pub fn room_list_stream( + &self, + ) -> (Vector, impl Stream>) { + let read_lock = self.inner.room_list.read().unwrap(); + let values = (*read_lock).clone(); + let subscriber = ObservableVector::subscribe(&read_lock); + (values, subscriber) } /// Get a stream of room list, but filtered. @@ -135,13 +143,13 @@ impl SlidingSyncList { /// by `filter`. pub fn room_list_filtered_stream( &self, - filter: Box bool + Sync + Send>, - ) -> FilteredVectorSubscriber bool + Sync + Send>> + filter: impl Fn(&RoomListEntry) -> bool + Sync + Send + 'static, + ) -> (Vector, FilteredVectorSubscriber) { - let (_, stream) = - ObservableVector::subscribe_filtered(&self.inner.room_list.read().unwrap(), filter); - - stream + ObservableVector::subscribe_filtered( + &self.inner.room_list.read().unwrap(), + Box::new(filter), + ) } /// Get the maximum number of rooms. See [`Self::maximum_number_of_rooms`]