Skip to content

Commit

Permalink
feat(ui,ffi): Implement the all and any filters on FFI.
Browse files Browse the repository at this point in the history
This patch implements the `all` and `any` filters in `matrix-sdk-ffi`.
The `not` filter cannot be implemented because recursive enum isn't
supported by UniFFI (see mozilla/uniffi-rs#396).
  • Loading branch information
Hywan committed Feb 7, 2024
1 parent 61d3f8d commit d699b2f
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 26 deletions.
52 changes: 37 additions & 15 deletions bindings/matrix-sdk-ffi/src/room_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};
Expand Down Expand Up @@ -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) {
Expand All @@ -416,12 +409,41 @@ impl RoomListDynamicEntriesController {

#[derive(uniffi::Enum)]
pub enum RoomListEntriesDynamicFilterKind {
All { filters: Vec<RoomListEntriesDynamicFilterKind> },
Any { filters: Vec<RoomListEntriesDynamicFilterKind> },
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<matrix_sdk_ui::room_list_service::Room>,
Expand Down
12 changes: 5 additions & 7 deletions crates/matrix-sdk-ui/src/room_list_service/room_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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).
Expand Down Expand Up @@ -199,7 +199,8 @@ pub enum RoomListLoadingState {
},
}

type BoxedFilterFn = Box<dyn Fn(&RoomListEntry) -> bool + Send + Sync>;
/// Type alias for a boxed filter function.
pub type BoxedFilterFn = Box<dyn Filter + Send + Sync>;

/// Controller for the [`RoomList`] dynamic entries.
///
Expand All @@ -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
}
}
Expand Down
8 changes: 4 additions & 4 deletions crates/matrix-sdk-ui/tests/integration/room_list_service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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! {
Expand Down Expand Up @@ -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! {
Expand All @@ -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! {
Expand All @@ -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! {
Expand Down

0 comments on commit d699b2f

Please sign in to comment.