From 16dcfb2e84aa9bca9499a8aa6c48b33672c29353 Mon Sep 17 00:00:00 2001 From: Stefan Ceriu Date: Sun, 25 Feb 2024 15:39:40 +0200 Subject: [PATCH] feat: Expose a room list filter for Invites only --- bindings/matrix-sdk-ffi/src/room_list.rs | 7 +- .../src/room_list_service/filters/invite.rs | 84 +++++++++++++++++++ .../src/room_list_service/filters/mod.rs | 2 + 3 files changed, 91 insertions(+), 2 deletions(-) create mode 100644 crates/matrix-sdk-ui/src/room_list_service/filters/invite.rs diff --git a/bindings/matrix-sdk-ffi/src/room_list.rs b/bindings/matrix-sdk-ffi/src/room_list.rs index 511c259d3..8437df88b 100644 --- a/bindings/matrix-sdk-ffi/src/room_list.rs +++ b/bindings/matrix-sdk-ffi/src/room_list.rs @@ -16,8 +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_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_non_left, + new_filter_none, new_filter_normalized_match_room_name, new_filter_unread, + RoomCategory, }, BoxedFilterFn, }, @@ -421,6 +422,7 @@ pub enum RoomListEntriesDynamicFilterKind { NonLeft, Unread, Favourite, + Invite, Category { expect: RoomListFilterCategory }, None, NormalizedMatchRoomName { pattern: String }, @@ -460,6 +462,7 @@ impl FilterWrapper { Kind::NonLeft => Self(Box::new(new_filter_non_left(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))), Kind::Category { expect } => Self(Box::new(new_filter_category(client, expect.into()))), Kind::None => Self(Box::new(new_filter_none())), Kind::NormalizedMatchRoomName { pattern } => { 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 new file mode 100644 index 000000000..146b41d8f --- /dev/null +++ b/crates/matrix-sdk-ui/src/room_list_service/filters/invite.rs @@ -0,0 +1,84 @@ +use matrix_sdk::{Client, RoomListEntry}; +use matrix_sdk_base::RoomState; + +use super::Filter; + +struct InviteRoomMatcher +where + F: Fn(&RoomListEntry) -> Option, +{ + is_invite: F, +} + +impl InviteRoomMatcher +where + F: Fn(&RoomListEntry) -> Option, +{ + fn matches(&self, room_list_entry: &RoomListEntry) -> bool { + if !matches!(room_list_entry, RoomListEntry::Filled(_) | RoomListEntry::Invalidated(_)) { + return false; + } + + (self.is_invite)(room_list_entry).unwrap_or(false) + } +} + +/// Create a new filter that will accept all filled or invalidated entries, but +/// filters out rooms that are not invites (see +/// [`matrix_sdk_base::RoomState::Invited`]). +pub fn new_filter(client: &Client) -> impl Filter { + let client = client.clone(); + + let matcher = InviteRoomMatcher { + is_invite: move |room| match room { + RoomListEntry::Filled(room_id) | RoomListEntry::Invalidated(room_id) => { + let room = client.get_room(room_id)?; + Some(room.state() == RoomState::Invited) + } + _ => None, + }, + }; + + move |room_list_entry| -> bool { matcher.matches(room_list_entry) } +} + +#[cfg(test)] +mod tests { + use std::ops::Not; + + use matrix_sdk::RoomListEntry; + use ruma::room_id; + + use super::InviteRoomMatcher; + + #[test] + fn test_is_invite() { + let matcher = InviteRoomMatcher { is_invite: |_| Some(true) }; + + assert!(matcher.matches(&RoomListEntry::Empty).not()); + assert!(matcher.matches(&RoomListEntry::Filled(room_id!("!r0:bar.org").to_owned()))); + assert!(matcher.matches(&RoomListEntry::Invalidated(room_id!("!r0:bar.org").to_owned()))); + } + + #[test] + fn test_is_not_invite() { + let matcher = InviteRoomMatcher { is_invite: |_| Some(false) }; + + assert!(matcher.matches(&RoomListEntry::Empty).not()); + assert!(matcher.matches(&RoomListEntry::Filled(room_id!("!r0:bar.org").to_owned())).not()); + assert!(matcher + .matches(&RoomListEntry::Invalidated(room_id!("!r0:bar.org").to_owned())) + .not()); + } + + #[test] + fn test_invite_state_cannot_be_found() { + let matcher = InviteRoomMatcher { is_invite: |_| None }; + + assert!(matcher.matches(&RoomListEntry::Empty).not()); + assert!(matcher.matches(&RoomListEntry::Filled(room_id!("!r0:bar.org").to_owned())).not()); + assert!(matcher + .matches(&RoomListEntry::Invalidated(room_id!("!r0:bar.org").to_owned())) + .not()); + } +} 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 012b5f32f..fdc667934 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 @@ -59,6 +59,7 @@ mod any; mod category; mod favourite; mod fuzzy_match_room_name; +mod invite; mod non_left; mod none; mod normalized_match_room_name; @@ -70,6 +71,7 @@ pub use any::new_filter as new_filter_any; 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; use matrix_sdk::RoomListEntry; pub use non_left::new_filter as new_filter_non_left; pub use none::new_filter as new_filter_none;