-
Notifications
You must be signed in to change notification settings - Fork 258
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Widget API: initial skeleton #2420
Conversation
Codecov ReportPatch coverage has no change and project coverage change:
Additional details and impacted files@@ Coverage Diff @@
## main #2420 +/- ##
==========================================
+ Coverage 77.11% 77.13% +0.02%
==========================================
Files 181 181
Lines 19166 19166
==========================================
+ Hits 14779 14784 +5
+ Misses 4387 4382 -5
☔ View full report in Codecov by Sentry. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the PR! I have a lot of feedback, but it should all be pretty straight-forward. If anything is unclear or you disagree with one of my suggestions, please reply instead of changing things in what seems to be the most appropriate way (this may be obvious, but I haven't interacted with you before and have had the latter happen multiple times 😅).
crates/matrix-sdk/src/lib.rs
Outdated
#[cfg(feature = "experimental-sliding-sync")] | ||
pub mod sliding_sync; | ||
|
||
#[cfg(feature = "widget-api")] | ||
pub mod widget_api; | ||
|
||
#[cfg(feature = "e2e-encryption")] | ||
pub mod encryption; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you remove the blank lines between all of the module declarations, and instead have just one to separate the mod
s from the pub use
s?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure. One question though: should I also remove the empty lines around the sliding_sync
. Rationale: I added pub mod widget_api
there since it was following the experimental sliding sync module which also was separated by spaces.
I.e. it was:
#[cfg(feature = "experimental-oidc")]
pub mod oidc;
pub mod room;
pub mod sync;
#[cfg(feature = "experimental-sliding-sync")]
pub mod sliding_sync;
#[cfg(feature = "e2e-encryption")]
pub mod encryption;
So I placed the pub mod widget_api
right after the pub mod sliding_sync
. I've pushed a change, hopefully I got it right.
} | ||
|
||
/// An alias for an actual type of the messages that is going to be used with a permission request. | ||
pub type MessageType = String; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is for a Matrix event type, and widgets might interact with both message events and state events, right? If yes, this type alias doesn't need to exist, we can use TimelineEventType
from ruma::events
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right (if I remember correctly). I actually wanted to also use stronger types here and had a discussion with @toger5, but as far as I can remember, @toger5's suggestion was that it can be any event type in theory and that there was no simple way to map them (no enum with a function f: EventType -> String
and f: String -> EventType
transformation). @toger5, could you chime in? 🙂
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are other "event" types that aren't part of TimelineEventType
, but I'm 99.5% certain that those are out of scope for the widget API. They are ephemeral or mutable things like typing and receipt events, account data and presence. Often when people talk about events, those are implicitly excluded (see also matrix-org/matrix-spec#897).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Widgets are allowed to introduce new unspecced message types. Just arbitrary strings for their own usecases. Does TimelineEevntType have a "other" enum case. If so this would very much be a better solution. If not it would be a shame if a widget is working with its own timeline event types but the widget driver is giving a parsing error.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does TimelineEevntType have a "other" enum case.
Yes,any string can be converted .into()
that type. The variant is hidden / opaque, but to check for a custom type, one can also convert the other way using .to_string()
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice! Updated.
Awesome! Btw, based on the feedback so far I very much appreciate the diligence and attention to detail! 👍 I was worried I'm the only one paying attention to such things 😄 P.S.: Apologies for not running this through |
Oh, maybe you ran rustfmt, but not nightly rustfmt. We use some rustfmt options that are unfortunately still unstable and only applied when running nightly rustfmt. Try |
Co-authored-by: Jonas Platte <jplatte+git@posteo.de>
Co-authored-by: Jonas Platte <jplatte+git@posteo.de>
Co-authored-by: Jonas Platte <jplatte+git@posteo.de>
Co-authored-by: Jonas Platte <jplatte+git@posteo.de>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would rename this module widget
instead of widget_api
. Just a personal taste compared to the rest of the SDK.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Though in that case, we should not have a widget
sub-module. Which is fine by me really, the items from that could be part of this module just as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also prefer short and concise names, I think the only reason we chose widget_api
originally was that we thought that if we call it widget
, it might be confused with the widget implementation (not the API, in our case the client widget API), but I'm totally fine with renaming it to widget
if that's your preference folks!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The client widget API couldn't live in this crate though, right? In that case, let's do the rename as suggested by Ivan.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated.
The client widget API couldn't live in this crate though, right?
The actual implementation of the run()
function and its internals. Originally I thought that it would live there, but maybe you're right and it's better to place the client widget API in a separate module or something like this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, then I guess I misunderstood what you meant by "client widget API". Anyways, let's figure this out when it comes to the next PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the conclusion from the discussion on Matrix is simply that we should replace timeline events by message-like event in the EventFilter
?
|
||
use async_trait::async_trait; | ||
|
||
use crate::ruma::events::{StateEventType, TimelineEventType}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use crate::ruma::events::{StateEventType, TimelineEventType}; | |
use crate::ruma::events::{MessageLikeEventType, StateEventType}; |
pub enum EventFilter { | ||
/// Filters for the timeline events, the `data` field is used to store the | ||
/// `msgtype`. | ||
Timeline(FilterContent<TimelineEventType>), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Timeline(FilterContent<TimelineEventType>), | |
MessageLike(FilterContent<MessageLikeEventType>), |
/// sending or for receiving). | ||
#[derive(Debug)] | ||
pub enum EventFilter { | ||
/// Filters for the timeline events, the `data` field is used to store the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/// Filters for the timeline events, the `data` field is used to store the | |
/// Filters for message-like events, the `data` field is used to store the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, I am now realizing that this filtering API is also suffering from the confusion between message events and m.room.message
events. Not every message(-like) event has a msgtype
, so please can you clarify what the role of the "timeline" filter is? Are widgets only supposed to interact with m.room.message
events, or state events? (an example of a different message-like event would be m.reaction
)
Co-authored-by: Jonas Platte <jplatte+git@posteo.de>
These are very valid questions!
From what I understand, it can interact with both state and message-like events, though among message-like events it only handles What about this: pub struct EventFilter {
pub event_type: TimelineEventType,
pub event_kind: EventKind,
}
pub enum EventKind {
StateEvent {
key: String,
},
MessageLikeEvent {
msgtype: Option<String>,
},
} Does this look sensible to you? |
I'd propose this instead: pub enum EventFilter {
MessageLike {
event_type: MessageLikeEventType,
/// Additional filter for the msgtype, only used for `m.room.message`.
msgtype: Option<String>,
}
State {
event_type: StateEventType,
state_key: String,
}
} And, final question: Should the |
The proposal makes sense 👍 Indeed, it can request permissions to read/send any state events. So, in this case, I suppose that the |
I think |
/// Whether or not the widget should be initialized on load message | ||
/// (`ContentLoad` message), or upon creation/attaching of the widget to | ||
/// the SDK's state machine that drives the API. | ||
pub init_on_load: bool, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should call it init_on_content_loaded
even with the doc text I can see how one interprets it as:
init_on_load -> the widget initializes when the I frame is attached/created/"loaded".
(But we want this bool to define define, that the widget is initialized once it sends us the content loaded action.
Hey @jplatte,
today, we had a sync-up with @toger5 on the current state of the Client Widget API implementation in the Rust SDK (we've been working on it for a few weeks). If my understanding is correct (@toger5, please correct me if I'm wrong), you wanted to see some "top-level boilerplate" that you could use in order to develop the FFI part of the Widget Client API inside the Rust SDK and check if it matches your expectations from the interface of the API.
We've implemented the part of the spec that should be sufficient for the integration of Element Call in Element X and currently we're working on the final steps to add proper error handling, ensuring that we did not miss anything, and testing it (@toger5 is on it). The latest state could be seen here: https://github.com/toger5/matrix-rust-sdk/blob/client-widget-api/crates/matrix-sdk/src/widget_api/mod.rs
This PR is a small subset of our branch which only includes the minimalistic "upper layer" of the API. We decided to create this small PR as if our understanding is right, you would prefer to see a simple interface before digging into 1.3k+ LOC PR for now 🙂 Additionally, our implementation in a branch misses some documentation and probably would need a round of
clippy
fixes to make sure that we have a clean implementation that would pass the CI.