diff --git a/crates/ruma-client-api/Cargo.toml b/crates/ruma-client-api/Cargo.toml index 28727702..bc122a56 100644 --- a/crates/ruma-client-api/Cargo.toml +++ b/crates/ruma-client-api/Cargo.toml @@ -18,6 +18,7 @@ rustdoc-args = ["--cfg", "docsrs"] compat = [] unstable-exhaustive-types = [] unstable-msc2448 = [] +unstable-msc3440 = [] unstable-msc3488 = [] client = [] server = [] diff --git a/crates/ruma-client-api/src/filter.rs b/crates/ruma-client-api/src/filter.rs index 5fbfba5e..760c7b38 100644 --- a/crates/ruma-client-api/src/filter.rs +++ b/crates/ruma-client-api/src/filter.rs @@ -48,6 +48,40 @@ impl Default for EventFormat { } } +/// Relation types as defined in `rel_type` of an `m.relates_to` field. +/// +/// This type can hold an arbitrary string. To check for formats that are not available as a +/// documented variant here, use its string representation, obtained through `.as_str()`. +#[derive(Clone, Debug, PartialEq, Eq, StringEnum)] +#[cfg(feature = "unstable-msc3440")] +#[non_exhaustive] +pub enum RelationType { + /// `m.annotation`, an annotation, principally used by reactions. + #[cfg(feature = "unstable-msc2677")] + #[ruma_enum(rename = "m.annotation")] + Annotation, + + /// `m.replace`, a replacement. + #[cfg(feature = "unstable-msc2676")] + #[ruma_enum(rename = "m.replace")] + Replacement, + + /// `m.thread`, a participant to a thread. + #[ruma_enum(rename = "io.element.thread")] + Thread, + + #[doc(hidden)] + _Custom(PrivOwnedStr), +} + +#[cfg(feature = "unstable-msc3440")] +impl RelationType { + /// Creates a string slice from this `RelationType`. + pub fn as_str(&self) -> &str { + self.as_ref() + } +} + /// Filters to be applied to room events. #[derive(Clone, Debug, Default, Outgoing, Serialize)] #[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)] @@ -111,6 +145,30 @@ pub struct RoomEventFilter<'a> { /// Defaults to `LazyLoadOptions::Disabled`. #[serde(flatten)] pub lazy_load_options: LazyLoadOptions, + + /// A list of relation types to include. + /// + /// An event A is included in the filter only if there exists another event B which relates to + /// A with a `rel_type` which is defined in the list. + #[cfg(feature = "unstable-msc3440")] + #[serde( + rename = "io.element.relation_types", + default, + skip_serializing_if = "<[_]>::is_empty" + )] + pub related_by_rel_types: &'a [RelationType], + + /// A list of senders to include. + /// + /// An event A is included in the filter only if there exists another event B which relates to + /// A, and which has a sender which is in the list. + #[cfg(feature = "unstable-msc3440")] + #[serde( + rename = "io.element.relation_senders", + default, + skip_serializing_if = "<[_]>::is_empty" + )] + pub related_by_senders: &'a [Box], } impl<'a> RoomEventFilter<'a> { @@ -128,7 +186,7 @@ impl<'a> RoomEventFilter<'a> { /// Returns `true` if all fields are empty. pub fn is_empty(&self) -> bool { - self.not_types.is_empty() + let empty = self.not_types.is_empty() && self.not_rooms.is_empty() && self.limit.is_none() && self.rooms.is_none() @@ -136,14 +194,20 @@ impl<'a> RoomEventFilter<'a> { && self.senders.is_none() && self.types.is_none() && self.url_filter.is_none() - && self.lazy_load_options.is_disabled() + && self.lazy_load_options.is_disabled(); + + #[cfg(not(feature = "unstable-msc3440"))] + return empty; + + #[cfg(feature = "unstable-msc3440")] + return empty && self.related_by_rel_types.is_empty() && self.related_by_senders.is_empty(); } } impl IncomingRoomEventFilter { /// Returns `true` if all fields are empty. pub fn is_empty(&self) -> bool { - self.not_types.is_empty() + let empty = self.not_types.is_empty() && self.not_rooms.is_empty() && self.limit.is_none() && self.rooms.is_none() @@ -151,7 +215,13 @@ impl IncomingRoomEventFilter { && self.senders.is_none() && self.types.is_none() && self.url_filter.is_none() - && self.lazy_load_options.is_disabled() + && self.lazy_load_options.is_disabled(); + + #[cfg(not(feature = "unstable-msc3440"))] + return empty; + + #[cfg(feature = "unstable-msc3440")] + return empty && self.related_by_rel_types.is_empty() && self.related_by_senders.is_empty(); } } @@ -470,10 +540,26 @@ mod tests { limit: None, url_filter: Some(UrlFilter::EventsWithUrl), lazy_load_options: LazyLoadOptions::Enabled { include_redundant_members: false }, - } if types == vec!["m.room.message".to_owned()] + #[cfg(feature = "unstable-msc3440")] + related_by_rel_types, + #[cfg(feature = "unstable-msc3440")] + related_by_senders + } if { + let valid = types == vec!["m.room.message".to_owned()] && not_types.is_empty() && not_rooms.is_empty() - && not_senders.is_empty() + && not_senders.is_empty(); + + #[cfg(not(feature = "unstable-msc3440"))] + { + valid + } + + #[cfg(feature = "unstable-msc3440")] + { + valid && related_by_rel_types.is_empty() && related_by_senders.is_empty() + } + } ); Ok(()) diff --git a/crates/ruma/Cargo.toml b/crates/ruma/Cargo.toml index cd082161..1f53acc2 100644 --- a/crates/ruma/Cargo.toml +++ b/crates/ruma/Cargo.toml @@ -118,7 +118,10 @@ unstable-msc2675 = ["ruma-common/unstable-msc2675"] unstable-msc2676 = ["ruma-common/unstable-msc2676"] unstable-msc2677 = ["ruma-common/unstable-msc2677"] unstable-msc3246 = ["ruma-common/unstable-msc3246"] -unstable-msc3440 = ["ruma-common/unstable-msc3440"] +unstable-msc3440 = [ + "ruma-client-api/unstable-msc3440", + "ruma-common/unstable-msc3440", +] unstable-msc3488 = [ "ruma-client-api/unstable-msc3488", "ruma-common/unstable-msc3488",