mirror of
https://github.com/matrix-org/matrix-rust-sdk.git
synced 2026-04-26 18:20:40 -04:00
feat(ui,ffi): Implement the all and any filters on FFI.
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 https://github.com/mozilla/uniffi-rs/issues/396).
This commit is contained in:
@@ -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<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>,
|
||||
|
||||
@@ -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<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.
|
||||
///
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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! {
|
||||
|
||||
Reference in New Issue
Block a user