diff --git a/bindings/matrix-sdk-ffi/src/room_list.rs b/bindings/matrix-sdk-ffi/src/room_list.rs index e9c8ccc2b..a0ddbe757 100644 --- a/bindings/matrix-sdk-ffi/src/room_list.rs +++ b/bindings/matrix-sdk-ffi/src/room_list.rs @@ -16,9 +16,9 @@ use matrix_sdk_ui::{ room_list_service::{ filters::{ new_filter_all, new_filter_any, new_filter_category, new_filter_favourite, - new_filter_fuzzy_match_room_name, new_filter_invite, new_filter_non_left, - new_filter_none, new_filter_normalized_match_room_name, new_filter_unread, - RoomCategory, + new_filter_fuzzy_match_room_name, new_filter_invite, new_filter_joined, + new_filter_non_left, new_filter_none, new_filter_normalized_match_room_name, + new_filter_unread, RoomCategory, }, BoxedFilterFn, }, @@ -423,6 +423,7 @@ pub enum RoomListEntriesDynamicFilterKind { All { filters: Vec }, Any { filters: Vec }, NonLeft, + Joined, Unread, Favourite, Invite, @@ -463,6 +464,7 @@ impl FilterWrapper { filters.into_iter().map(|filter| FilterWrapper::from(client, filter).0).collect(), ))), Kind::NonLeft => Self(Box::new(new_filter_non_left(client))), + Kind::Joined => Self(Box::new(new_filter_joined(client))), Kind::Unread => Self(Box::new(new_filter_unread(client))), Kind::Favourite => Self(Box::new(new_filter_favourite(client))), Kind::Invite => Self(Box::new(new_filter_invite(client))), diff --git a/crates/matrix-sdk-ui/src/room_list_service/filters/invite.rs b/crates/matrix-sdk-ui/src/room_list_service/filters/invite.rs index 661981524..e07f3462b 100644 --- a/crates/matrix-sdk-ui/src/room_list_service/filters/invite.rs +++ b/crates/matrix-sdk-ui/src/room_list_service/filters/invite.rs @@ -72,7 +72,7 @@ mod tests { assert!(!matcher.matches(&RoomListEntry::Filled(room_id!("!r0:bar.org").to_owned()))); assert!(!matcher.matches(&RoomListEntry::Invalidated(room_id!("!r0:bar.org").to_owned()))); - // When a room has been joined, it does match (unless it's empty). + // When a room is an invite, it does match (unless it's empty). let matcher = InviteRoomMatcher { state: |_| Some(RoomState::Invited) }; assert!(!matcher.matches(&RoomListEntry::Empty)); assert!(matcher.matches(&RoomListEntry::Filled(room_id!("!r0:bar.org").to_owned()))); diff --git a/crates/matrix-sdk-ui/src/room_list_service/filters/joined.rs b/crates/matrix-sdk-ui/src/room_list_service/filters/joined.rs new file mode 100644 index 000000000..cf7eb6ca4 --- /dev/null +++ b/crates/matrix-sdk-ui/src/room_list_service/filters/joined.rs @@ -0,0 +1,81 @@ +use matrix_sdk::{Client, RoomListEntry}; +use matrix_sdk_base::RoomState; + +use super::Filter; + +struct JoinedRoomMatcher +where + F: Fn(&RoomListEntry) -> Option, +{ + state: F, +} + +impl JoinedRoomMatcher +where + F: Fn(&RoomListEntry) -> Option, +{ + fn matches(&self, room: &RoomListEntry) -> bool { + if !matches!(room, RoomListEntry::Filled(_) | RoomListEntry::Invalidated(_)) { + return false; + } + + if let Some(state) = (self.state)(room) { + state == RoomState::Joined + } else { + false + } + } +} + +/// Create a new filter that will accept all filled or invalidated entries, but +/// filters out rooms that are not joined (see +/// [`matrix_sdk_base::RoomState::Joined`]). +pub fn new_filter(client: &Client) -> impl Filter { + let client = client.clone(); + + let matcher = JoinedRoomMatcher { + state: move |room| { + let room_id = room.as_room_id()?; + let room = client.get_room(room_id)?; + Some(room.state()) + }, + }; + + move |room_list_entry| -> bool { matcher.matches(room_list_entry) } +} + +#[cfg(test)] +mod tests { + use matrix_sdk::RoomListEntry; + use matrix_sdk_base::RoomState; + use ruma::room_id; + + use super::JoinedRoomMatcher; + + #[test] + fn test_all_joined_kind_of_room_list_entry() { + // When we can't figure out the room state, nothing matches. + let matcher = JoinedRoomMatcher { state: |_| None }; + assert!(!matcher.matches(&RoomListEntry::Empty)); + assert!(!matcher.matches(&RoomListEntry::Filled(room_id!("!r0:bar.org").to_owned()))); + assert!(!matcher.matches(&RoomListEntry::Invalidated(room_id!("!r0:bar.org").to_owned()))); + + // When a room has been left, it doesn't match. + let matcher = JoinedRoomMatcher { state: |_| Some(RoomState::Left) }; + assert!(!matcher.matches(&RoomListEntry::Empty)); + assert!(!matcher.matches(&RoomListEntry::Filled(room_id!("!r0:bar.org").to_owned()))); + assert!(!matcher.matches(&RoomListEntry::Invalidated(room_id!("!r0:bar.org").to_owned()))); + + // When a room is an invite, it doesn't match. + let matcher = JoinedRoomMatcher { state: |_| Some(RoomState::Invited) }; + assert!(!matcher.matches(&RoomListEntry::Empty)); + assert!(!matcher.matches(&RoomListEntry::Filled(room_id!("!r0:bar.org").to_owned()))); + assert!(!matcher.matches(&RoomListEntry::Invalidated(room_id!("!r0:bar.org").to_owned()))); + + // When a room has been joined, it does match (unless it's empty). + let matcher = JoinedRoomMatcher { state: |_| Some(RoomState::Joined) }; + assert!(!matcher.matches(&RoomListEntry::Empty)); + assert!(matcher.matches(&RoomListEntry::Filled(room_id!("!r0:bar.org").to_owned()))); + assert!(matcher.matches(&RoomListEntry::Invalidated(room_id!("!r0:bar.org").to_owned()))); + } +} diff --git a/crates/matrix-sdk-ui/src/room_list_service/filters/mod.rs b/crates/matrix-sdk-ui/src/room_list_service/filters/mod.rs index fdc667934..1d8eeec49 100644 --- a/crates/matrix-sdk-ui/src/room_list_service/filters/mod.rs +++ b/crates/matrix-sdk-ui/src/room_list_service/filters/mod.rs @@ -60,6 +60,7 @@ mod category; mod favourite; mod fuzzy_match_room_name; mod invite; +mod joined; mod non_left; mod none; mod normalized_match_room_name; @@ -72,6 +73,7 @@ pub use category::{new_filter as new_filter_category, RoomCategory}; pub use favourite::new_filter as new_filter_favourite; pub use fuzzy_match_room_name::new_filter as new_filter_fuzzy_match_room_name; pub use invite::new_filter as new_filter_invite; +pub use joined::new_filter as new_filter_joined; use matrix_sdk::RoomListEntry; pub use non_left::new_filter as new_filter_non_left; pub use none::new_filter as new_filter_none;