diff --git a/bindings/matrix-sdk-ffi/src/room_list.rs b/bindings/matrix-sdk-ffi/src/room_list.rs index ff07e143f..5c6731bef 100644 --- a/bindings/matrix-sdk-ffi/src/room_list.rs +++ b/bindings/matrix-sdk-ffi/src/room_list.rs @@ -13,9 +13,12 @@ use matrix_sdk::{ RoomListEntry as MatrixRoomListEntry, }; use matrix_sdk_ui::{ - room_list_service::filters::{ - new_filter_fuzzy_match_room_name, new_filter_non_left, new_filter_none, - new_filter_normalized_match_room_name, + room_list_service::{ + filters::{ + new_filter_all, new_filter_any, new_filter_fuzzy_match_room_name, new_filter_non_left, + new_filter_none, new_filter_normalized_match_room_name, + }, + BoxedFilterFn, }, timeline::default_event_filter, }; @@ -391,18 +394,8 @@ impl RoomListDynamicEntriesController { #[uniffi::export] impl RoomListDynamicEntriesController { fn set_filter(&self, kind: RoomListEntriesDynamicFilterKind) -> bool { - use RoomListEntriesDynamicFilterKind as Kind; - - match kind { - Kind::NonLeft => self.inner.set_filter(new_filter_non_left(&self.client)), - Kind::None => self.inner.set_filter(new_filter_none()), - Kind::NormalizedMatchRoomName { pattern } => { - self.inner.set_filter(new_filter_normalized_match_room_name(&self.client, &pattern)) - } - Kind::FuzzyMatchRoomName { pattern } => { - self.inner.set_filter(new_filter_fuzzy_match_room_name(&self.client, &pattern)) - } - } + let FilterWrapper(filter) = FilterWrapper::from(&self.client, kind); + self.inner.set_filter(filter) } fn add_one_page(&self) { @@ -416,12 +409,41 @@ impl RoomListDynamicEntriesController { #[derive(uniffi::Enum)] pub enum RoomListEntriesDynamicFilterKind { + All { filters: Vec }, + Any { filters: Vec }, NonLeft, None, NormalizedMatchRoomName { pattern: String }, FuzzyMatchRoomName { pattern: String }, } +/// Custom internal type to transform a `RoomListEntriesDynamicFilterKind` into +/// a `BoxedFilterFn`. +struct FilterWrapper(BoxedFilterFn); + +impl FilterWrapper { + fn from(client: &matrix_sdk::Client, value: RoomListEntriesDynamicFilterKind) -> Self { + use RoomListEntriesDynamicFilterKind as Kind; + + match value { + Kind::All { filters } => Self(Box::new(new_filter_all( + filters.into_iter().map(|filter| FilterWrapper::from(client, filter).0).collect(), + ))), + Kind::Any { filters } => Self(Box::new(new_filter_any( + filters.into_iter().map(|filter| FilterWrapper::from(client, filter).0).collect(), + ))), + Kind::NonLeft => Self(Box::new(new_filter_non_left(client))), + Kind::None => Self(Box::new(new_filter_none())), + Kind::NormalizedMatchRoomName { pattern } => { + Self(Box::new(new_filter_normalized_match_room_name(client, &pattern))) + } + Kind::FuzzyMatchRoomName { pattern } => { + Self(Box::new(new_filter_fuzzy_match_room_name(client, &pattern))) + } + } + } +} + #[derive(uniffi::Object)] pub struct RoomListItem { inner: Arc, diff --git a/crates/matrix-sdk-ui/src/room_list_service/room_list.rs b/crates/matrix-sdk-ui/src/room_list_service/room_list.rs index 405514978..93d1e6763 100644 --- a/crates/matrix-sdk-ui/src/room_list_service/room_list.rs +++ b/crates/matrix-sdk-ui/src/room_list_service/room_list.rs @@ -26,7 +26,7 @@ use matrix_sdk::{ RoomListEntry, SlidingSync, SlidingSyncList, }; -use super::{Error, State}; +use super::{filters::Filter, Error, State}; /// A `RoomList` represents a list of rooms, from a /// [`RoomListService`](super::RoomListService). @@ -199,7 +199,8 @@ pub enum RoomListLoadingState { }, } -type BoxedFilterFn = Box bool + Send + Sync>; +/// Type alias for a boxed filter function. +pub type BoxedFilterFn = Box; /// Controller for the [`RoomList`] dynamic entries. /// @@ -226,17 +227,14 @@ impl RoomListDynamicEntriesController { /// /// If the associated stream has been dropped, returns `false` to indicate /// the operation didn't have an effect. - pub fn set_filter( - &self, - filter: impl Fn(&RoomListEntry) -> bool + Send + Sync + 'static, - ) -> bool { + pub fn set_filter(&self, filter: BoxedFilterFn) -> bool { if Arc::strong_count(&self.filter) == 1 { // there is no other reference to the boxed filter fn, setting it // would be pointless (no new references can be created from self, // either) false } else { - self.filter.set(Box::new(filter)); + self.filter.set(filter); true } } diff --git a/crates/matrix-sdk-ui/tests/integration/room_list_service.rs b/crates/matrix-sdk-ui/tests/integration/room_list_service.rs index 87b58897d..276e54280 100644 --- a/crates/matrix-sdk-ui/tests/integration/room_list_service.rs +++ b/crates/matrix-sdk-ui/tests/integration/room_list_service.rs @@ -1643,7 +1643,7 @@ async fn test_dynamic_entries_stream() -> Result<(), Error> { assert_pending!(dynamic_entries_stream); // Now, let's define a filter. - dynamic_entries.set_filter(new_filter_fuzzy_match_room_name(&client, "mat ba")); + dynamic_entries.set_filter(Box::new(new_filter_fuzzy_match_room_name(&client, "mat ba"))); // Assert the dynamic entries. assert_entries_batch! { @@ -1799,7 +1799,7 @@ async fn test_dynamic_entries_stream() -> Result<(), Error> { assert_pending!(dynamic_entries_stream); // Now, let's change the dynamic entries! - dynamic_entries.set_filter(new_filter_fuzzy_match_room_name(&client, "hell")); + dynamic_entries.set_filter(Box::new(new_filter_fuzzy_match_room_name(&client, "hell"))); // Assert the dynamic entries. assert_entries_batch! { @@ -1811,7 +1811,7 @@ async fn test_dynamic_entries_stream() -> Result<(), Error> { assert_pending!(dynamic_entries_stream); // Now, let's change again the dynamic filter! - dynamic_entries.set_filter(new_filter_none()); + dynamic_entries.set_filter(Box::new(new_filter_none())); // Assert the dynamic entries. assert_entries_batch! { @@ -1822,7 +1822,7 @@ async fn test_dynamic_entries_stream() -> Result<(), Error> { }; // Now, let's change again the dynamic filter! - dynamic_entries.set_filter(new_filter_non_left(&client)); + dynamic_entries.set_filter(Box::new(new_filter_non_left(&client))); // Assert the dynamic entries. assert_entries_batch! {