Skip to content

Commit 9f38056

Browse files
committed
WidgetDriver: refactor Filter and introduce ToDeviceFilter
ToDevice events need their own custom filter type. Introducing this new filter type is the main purpose of this commit. The API for the filters was a bit confusing since it had a lot of special cases. This commit also simplifies the filter public api. Rethinking the public api we only need: - to know if events can be sent based on the capabilities - to know if events can be sent to the widget (read) based on the capabilities - if it even makes sense to sent a cs api read request or if all possibly returned events would not match the type. To simplify the code in the machine it also made sense to add `From` implementation to the FilterInputs instead of gathering the relevant data from all kinds of Raw events. The new api is simpler: All possible events we need to check can be converted into filter inputs (using `into()`). `capabilites` has two allow_read/allow_send that consume filter inputs. `capabilites` can be asked if there is any filter for specific event types to allow not send unnecassary requests.
1 parent d2874af commit 9f38056

File tree

5 files changed

+317
-271
lines changed

5 files changed

+317
-271
lines changed

bindings/matrix-sdk-ffi/src/widget.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -490,7 +490,7 @@ pub enum WidgetEventFilter {
490490
StateWithTypeAndStateKey { event_type: String, state_key: String },
491491
}
492492

493-
impl From<WidgetEventFilter> for matrix_sdk::widget::EventFilter {
493+
impl From<WidgetEventFilter> for matrix_sdk::widget::Filter {
494494
fn from(value: WidgetEventFilter) -> Self {
495495
match value {
496496
WidgetEventFilter::MessageLikeWithType { event_type } => {
@@ -509,9 +509,9 @@ impl From<WidgetEventFilter> for matrix_sdk::widget::EventFilter {
509509
}
510510
}
511511

512-
impl From<matrix_sdk::widget::EventFilter> for WidgetEventFilter {
513-
fn from(value: matrix_sdk::widget::EventFilter) -> Self {
514-
use matrix_sdk::widget::EventFilter as F;
512+
impl From<matrix_sdk::widget::Filter> for WidgetEventFilter {
513+
fn from(value: matrix_sdk::widget::Filter) -> Self {
514+
use matrix_sdk::widget::Filter as F;
515515

516516
match value {
517517
F::MessageLike(MessageLikeEventFilter::WithType(event_type)) => {

crates/matrix-sdk/src/widget/capabilities.rs

Lines changed: 50 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,12 @@
1818
use std::fmt;
1919

2020
use async_trait::async_trait;
21-
use ruma::{events::AnyTimelineEvent, serde::Raw};
2221
use serde::{ser::SerializeSeq, Deserialize, Deserializer, Serialize, Serializer};
23-
use tracing::{debug, error};
22+
use tracing::debug;
2423

2524
use super::{
26-
filter::MatrixEventFilterInput, EventFilter, MessageLikeEventFilter, StateEventFilter,
25+
filter::{Filter, FilterInput},
26+
MessageLikeEventFilter, StateEventFilter,
2727
};
2828

2929
/// Must be implemented by a component that provides functionality of deciding
@@ -42,9 +42,9 @@ pub trait CapabilitiesProvider: Send + Sync + 'static {
4242
#[cfg_attr(test, derive(PartialEq))]
4343
pub struct Capabilities {
4444
/// Types of the messages that a widget wants to be able to fetch.
45-
pub read: Vec<EventFilter>,
45+
pub read: Vec<Filter>,
4646
/// Types of the messages that a widget wants to be able to send.
47-
pub send: Vec<EventFilter>,
47+
pub send: Vec<Filter>,
4848
/// If this capability is requested by the widget, it can not operate
4949
/// separately from the matrix client.
5050
///
@@ -58,17 +58,29 @@ pub struct Capabilities {
5858
}
5959

6060
impl Capabilities {
61-
/// Tells if a given raw event matches the read filter.
62-
pub fn raw_event_matches_read_filter(&self, raw: &Raw<AnyTimelineEvent>) -> bool {
63-
let filter_in = match raw.deserialize_as::<MatrixEventFilterInput>() {
64-
Ok(filter) => filter,
65-
Err(err) => {
66-
error!("Failed to deserialize raw event as MatrixEventFilterInput: {err}");
67-
return false;
68-
}
69-
};
61+
/// Checks if a givent event is allowed to be forwarded to the widget.
62+
///
63+
/// - `event_filter_input` is a minimized event respresntation that contains
64+
/// only the information needed to check if the widget is allowed to
65+
/// receive the event. (See [`FilterInput`])
66+
pub(super) fn allow_reading(&self, event_filter_input: &FilterInput) -> bool {
67+
self.read.iter().any(|f| f.matches(event_filter_input))
68+
}
7069

71-
self.read.iter().any(|f| f.matches(&filter_in))
70+
/// Checks if a givent event is allowed to be sent by the widget.
71+
///
72+
/// - `event_filter_input` is a minimized event respresntation that contains
73+
/// only the information needed to check if the widget is allowed to send
74+
/// the event to a matrix room. (See [`FilterInput`])
75+
pub(super) fn allow_sending(&self, event_filter_input: &FilterInput) -> bool {
76+
self.send.iter().any(|f| f.matches(event_filter_input))
77+
}
78+
79+
/// Checks if a filter exists for the given event type, useful for
80+
/// optimization. Avoids unnecessary read event requests when no matching
81+
/// filter is present.
82+
pub(super) fn has_read_filter_for_type(&self, event_type: &str) -> bool {
83+
self.read.iter().any(|f| f.filter_event_type() == event_type)
7284
}
7385
}
7486

@@ -85,12 +97,12 @@ impl Serialize for Capabilities {
8597
where
8698
S: Serializer,
8799
{
88-
struct PrintEventFilter<'a>(&'a EventFilter);
100+
struct PrintEventFilter<'a>(&'a Filter);
89101
impl fmt::Display for PrintEventFilter<'_> {
90102
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
91103
match self.0 {
92-
EventFilter::MessageLike(filter) => PrintMessageLikeEventFilter(filter).fmt(f),
93-
EventFilter::State(filter) => PrintStateEventFilter(filter).fmt(f),
104+
Filter::MessageLike(filter) => PrintMessageLikeEventFilter(filter).fmt(f),
105+
Filter::State(filter) => PrintStateEventFilter(filter).fmt(f),
94106
}
95107
}
96108
}
@@ -136,15 +148,15 @@ impl Serialize for Capabilities {
136148
}
137149
for filter in &self.read {
138150
let name = match filter {
139-
EventFilter::MessageLike(_) => READ_EVENT,
140-
EventFilter::State(_) => READ_STATE,
151+
Filter::MessageLike(_) => READ_EVENT,
152+
Filter::State(_) => READ_STATE,
141153
};
142154
seq.serialize_element(&format!("{name}:{}", PrintEventFilter(filter)))?;
143155
}
144156
for filter in &self.send {
145157
let name = match filter {
146-
EventFilter::MessageLike(_) => SEND_EVENT,
147-
EventFilter::State(_) => SEND_STATE,
158+
Filter::MessageLike(_) => SEND_EVENT,
159+
Filter::State(_) => SEND_STATE,
148160
};
149161
seq.serialize_element(&format!("{name}:{}", PrintEventFilter(filter)))?;
150162
}
@@ -162,8 +174,8 @@ impl<'de> Deserialize<'de> for Capabilities {
162174
RequiresClient,
163175
UpdateDelayedEvent,
164176
SendDelayedEvent,
165-
Read(EventFilter),
166-
Send(EventFilter),
177+
Read(Filter),
178+
Send(Filter),
167179
Unknown,
168180
}
169181

@@ -184,17 +196,17 @@ impl<'de> Deserialize<'de> for Capabilities {
184196
}
185197

186198
match s.split_once(':') {
187-
Some((READ_EVENT, filter_s)) => Ok(Permission::Read(EventFilter::MessageLike(
199+
Some((READ_EVENT, filter_s)) => Ok(Permission::Read(Filter::MessageLike(
188200
parse_message_event_filter(filter_s),
189201
))),
190-
Some((SEND_EVENT, filter_s)) => Ok(Permission::Send(EventFilter::MessageLike(
202+
Some((SEND_EVENT, filter_s)) => Ok(Permission::Send(Filter::MessageLike(
191203
parse_message_event_filter(filter_s),
192204
))),
193205
Some((READ_STATE, filter_s)) => {
194-
Ok(Permission::Read(EventFilter::State(parse_state_event_filter(filter_s))))
206+
Ok(Permission::Read(Filter::State(parse_state_event_filter(filter_s))))
195207
}
196208
Some((SEND_STATE, filter_s)) => {
197-
Ok(Permission::Send(EventFilter::State(parse_state_event_filter(filter_s))))
209+
Ok(Permission::Send(Filter::State(parse_state_event_filter(filter_s))))
198210
}
199211
_ => {
200212
debug!("Unknown capability `{s}`");
@@ -272,19 +284,17 @@ mod tests {
272284
let parsed = serde_json::from_str::<Capabilities>(capabilities_str).unwrap();
273285
let expected = Capabilities {
274286
read: vec![
275-
EventFilter::MessageLike(MessageLikeEventFilter::WithType(
287+
Filter::MessageLike(MessageLikeEventFilter::WithType(
276288
"org.matrix.rageshake_request".into(),
277289
)),
278-
EventFilter::State(StateEventFilter::WithType(StateEventType::RoomMember)),
279-
EventFilter::State(StateEventFilter::WithType(
280-
"org.matrix.msc3401.call.member".into(),
281-
)),
290+
Filter::State(StateEventFilter::WithType(StateEventType::RoomMember)),
291+
Filter::State(StateEventFilter::WithType("org.matrix.msc3401.call.member".into())),
282292
],
283293
send: vec![
284-
EventFilter::MessageLike(MessageLikeEventFilter::WithType(
294+
Filter::MessageLike(MessageLikeEventFilter::WithType(
285295
"org.matrix.rageshake_request".into(),
286296
)),
287-
EventFilter::State(StateEventFilter::WithTypeAndStateKey(
297+
Filter::State(StateEventFilter::WithTypeAndStateKey(
288298
"org.matrix.msc3401.call.member".into(),
289299
"@user:matrix.server".into(),
290300
)),
@@ -301,20 +311,16 @@ mod tests {
301311
fn serialization_and_deserialization_are_symmetrical() {
302312
let capabilities = Capabilities {
303313
read: vec![
304-
EventFilter::MessageLike(MessageLikeEventFilter::WithType(
305-
"io.element.custom".into(),
306-
)),
307-
EventFilter::State(StateEventFilter::WithType(StateEventType::RoomMember)),
308-
EventFilter::State(StateEventFilter::WithTypeAndStateKey(
314+
Filter::MessageLike(MessageLikeEventFilter::WithType("io.element.custom".into())),
315+
Filter::State(StateEventFilter::WithType(StateEventType::RoomMember)),
316+
Filter::State(StateEventFilter::WithTypeAndStateKey(
309317
"org.matrix.msc3401.call.member".into(),
310318
"@user:matrix.server".into(),
311319
)),
312320
],
313321
send: vec![
314-
EventFilter::MessageLike(MessageLikeEventFilter::WithType(
315-
"io.element.custom".into(),
316-
)),
317-
EventFilter::State(StateEventFilter::WithTypeAndStateKey(
322+
Filter::MessageLike(MessageLikeEventFilter::WithType("io.element.custom".into())),
323+
Filter::State(StateEventFilter::WithTypeAndStateKey(
318324
"org.matrix.msc3401.call.member".into(),
319325
"@user:matrix.server".into(),
320326
)),

0 commit comments

Comments
 (0)