mirror of
https://github.com/matrix-org/matrix-rust-sdk.git
synced 2026-05-18 13:40:55 -04:00
widget: Add support for read-state-event fromWidget requests
Co-authored-by: Daniel Abramov <daniel.abramov@element.io>
This commit is contained in:
committed by
Jonas Platte
parent
946976a561
commit
3ce7126d58
@@ -24,7 +24,7 @@ use ruma::{
|
||||
use tracing::error;
|
||||
|
||||
use super::{
|
||||
actions::{MatrixDriverRequestData, ReadMessageLikeEventCommand},
|
||||
actions::{MatrixDriverRequestData, ReadMessageLikeEventCommand, ReadStateEventCommand},
|
||||
incoming::MatrixDriverResponse,
|
||||
MatrixDriverRequestMeta, SendEventCommand, WidgetMachine,
|
||||
};
|
||||
@@ -129,15 +129,15 @@ impl FromMatrixDriverResponse for request_openid_token::v3::Response {
|
||||
/// Ask the client to read matrix event(s) that corresponds to the given
|
||||
/// description and return a list of events as a response.
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct ReadMatrixEvent(pub(crate) ReadMessageLikeEventCommand);
|
||||
pub(crate) struct ReadMatrixMessageLikeEvent(pub(crate) ReadMessageLikeEventCommand);
|
||||
|
||||
impl From<ReadMatrixEvent> for MatrixDriverRequestData {
|
||||
fn from(value: ReadMatrixEvent) -> Self {
|
||||
impl From<ReadMatrixMessageLikeEvent> for MatrixDriverRequestData {
|
||||
fn from(value: ReadMatrixMessageLikeEvent) -> Self {
|
||||
MatrixDriverRequestData::ReadMessageLikeEvent(value.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl MatrixDriverRequest for ReadMatrixEvent {
|
||||
impl MatrixDriverRequest for ReadMatrixMessageLikeEvent {
|
||||
type Response = Vec<Raw<AnyTimelineEvent>>;
|
||||
}
|
||||
|
||||
@@ -153,6 +153,21 @@ impl FromMatrixDriverResponse for Vec<Raw<AnyTimelineEvent>> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Ask the client to read matrix event(s) that corresponds to the given
|
||||
/// description and return a list of events as a response.
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct ReadMatrixStateEvent(pub(crate) ReadStateEventCommand);
|
||||
|
||||
impl From<ReadMatrixStateEvent> for MatrixDriverRequestData {
|
||||
fn from(value: ReadMatrixStateEvent) -> Self {
|
||||
MatrixDriverRequestData::ReadStateEvent(value.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl MatrixDriverRequest for ReadMatrixStateEvent {
|
||||
type Response = Vec<Raw<AnyTimelineEvent>>;
|
||||
}
|
||||
|
||||
/// Ask the client to send matrix event that corresponds to the given
|
||||
/// description and return an event ID as a response.
|
||||
#[derive(Debug)]
|
||||
|
||||
@@ -14,13 +14,21 @@
|
||||
|
||||
use std::fmt;
|
||||
|
||||
use ruma::{
|
||||
events::{AnyTimelineEvent, MessageLikeEventType, StateEventType},
|
||||
serde::Raw,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::widget::StateKeySelector;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[serde(tag = "action", rename_all = "snake_case", content = "data")]
|
||||
pub(super) enum FromWidgetRequest {
|
||||
SupportedApiVersions {},
|
||||
ContentLoaded {},
|
||||
#[serde(rename = "org.matrix.msc2876.read_events")]
|
||||
ReadEvent(ReadEventRequest),
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
@@ -97,3 +105,24 @@ pub(super) enum ApiVersion {
|
||||
#[serde(rename = "town.robin.msc3846")]
|
||||
MSC3846,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[serde(untagged)]
|
||||
pub(super) enum ReadEventRequest {
|
||||
ReadStateEvent {
|
||||
#[serde(rename = "type")]
|
||||
event_type: StateEventType,
|
||||
state_key: StateKeySelector,
|
||||
},
|
||||
#[allow(dead_code)]
|
||||
ReadMessageLikeEvent {
|
||||
#[serde(rename = "type")]
|
||||
event_type: MessageLikeEventType,
|
||||
limit: Option<u32>,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub(super) struct ReadEventResponse {
|
||||
pub(super) events: Vec<Raw<AnyTimelineEvent>>,
|
||||
}
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
#![warn(unreachable_pub)]
|
||||
|
||||
use std::fmt;
|
||||
|
||||
use indexmap::{map::Entry, IndexMap};
|
||||
use ruma::serde::{JsonObject, Raw};
|
||||
use serde::Serialize;
|
||||
@@ -25,14 +27,26 @@ use tracing::{error, info_span, instrument, trace, warn};
|
||||
use uuid::Uuid;
|
||||
|
||||
use self::{
|
||||
driver_req::{AcquireCapabilities, MatrixDriverRequest, MatrixDriverRequestHandle},
|
||||
from_widget::{FromWidgetErrorResponse, FromWidgetRequest, SupportedApiVersionsResponse},
|
||||
actions::ReadStateEventCommand,
|
||||
driver_req::{
|
||||
AcquireCapabilities, MatrixDriverRequest, MatrixDriverRequestHandle, ReadMatrixStateEvent,
|
||||
},
|
||||
from_widget::{
|
||||
FromWidgetErrorResponse, FromWidgetRequest, ReadEventRequest, ReadEventResponse,
|
||||
SupportedApiVersionsResponse,
|
||||
},
|
||||
incoming::{IncomingWidgetMessage, IncomingWidgetMessageKind},
|
||||
to_widget::{
|
||||
NotifyPermissionsChanged, RequestPermissions, ToWidgetRequest, ToWidgetRequestHandle,
|
||||
ToWidgetResponse,
|
||||
},
|
||||
};
|
||||
#[cfg(doc)]
|
||||
use super::WidgetDriver;
|
||||
use super::{
|
||||
filter::{MatrixEventContent, MatrixEventFilterInput},
|
||||
Capabilities, StateKeySelector,
|
||||
};
|
||||
|
||||
mod actions;
|
||||
mod driver_req;
|
||||
@@ -47,9 +61,6 @@ pub(crate) use self::{
|
||||
actions::{Action, MatrixDriverRequestData, SendEventCommand},
|
||||
incoming::{IncomingMessage, MatrixDriverResponse},
|
||||
};
|
||||
use super::Capabilities;
|
||||
#[cfg(doc)]
|
||||
use super::WidgetDriver;
|
||||
|
||||
/// No I/O state machine.
|
||||
///
|
||||
@@ -134,7 +145,7 @@ impl WidgetMachine {
|
||||
let request = match raw_request.deserialize() {
|
||||
Ok(r) => r,
|
||||
Err(e) => {
|
||||
self.send_from_widget_response(raw_request, FromWidgetErrorResponse::new(e));
|
||||
self.send_from_widget_error_response(raw_request, e);
|
||||
return;
|
||||
}
|
||||
};
|
||||
@@ -143,12 +154,70 @@ impl WidgetMachine {
|
||||
FromWidgetRequest::SupportedApiVersions {} => {
|
||||
self.send_from_widget_response(raw_request, SupportedApiVersionsResponse::new());
|
||||
}
|
||||
|
||||
FromWidgetRequest::ContentLoaded {} => {
|
||||
self.send_from_widget_response(raw_request, JsonObject::new());
|
||||
if self.capabilities.is_unset() {
|
||||
self.negotiate_capabilities();
|
||||
}
|
||||
}
|
||||
|
||||
FromWidgetRequest::ReadEvent(req) => {
|
||||
self.process_read_event_request(req, raw_request);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn process_read_event_request(
|
||||
&mut self,
|
||||
request: ReadEventRequest,
|
||||
raw_request: Raw<FromWidgetRequest>,
|
||||
) {
|
||||
let CapabilitiesState::Negotiated(capabilities) = &self.capabilities else {
|
||||
self.send_from_widget_error_response(
|
||||
raw_request,
|
||||
"Received read event request before capabilities were negotiated",
|
||||
);
|
||||
return;
|
||||
};
|
||||
|
||||
match request {
|
||||
ReadEventRequest::ReadMessageLikeEvent { .. } => {
|
||||
self.send_from_widget_error_response(
|
||||
raw_request,
|
||||
"Reading of message events is not yet supported",
|
||||
);
|
||||
}
|
||||
ReadEventRequest::ReadStateEvent { event_type, state_key } => {
|
||||
let allowed = match &state_key {
|
||||
StateKeySelector::Any => capabilities
|
||||
.read
|
||||
.iter()
|
||||
.any(|filter| filter.matches_state_event_with_any_state_key(&event_type)),
|
||||
|
||||
StateKeySelector::Key(state_key) => {
|
||||
let filter_in = MatrixEventFilterInput {
|
||||
event_type: event_type.to_string().into(),
|
||||
state_key: Some(state_key.clone()),
|
||||
// content doesn't matter for state events
|
||||
content: MatrixEventContent::default(),
|
||||
};
|
||||
|
||||
capabilities.read.iter().any(|filter| filter.matches(&filter_in))
|
||||
}
|
||||
};
|
||||
|
||||
if allowed {
|
||||
let request =
|
||||
ReadMatrixStateEvent(ReadStateEventCommand { event_type, state_key });
|
||||
self.send_matrix_driver_request(request).then(|events, machine| {
|
||||
machine
|
||||
.send_from_widget_response(raw_request, ReadEventResponse { events });
|
||||
});
|
||||
} else {
|
||||
self.send_from_widget_error_response(raw_request, "Not allowed");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -240,6 +309,14 @@ impl WidgetMachine {
|
||||
}
|
||||
}
|
||||
|
||||
fn send_from_widget_error_response(
|
||||
&self,
|
||||
raw_request: Raw<FromWidgetRequest>,
|
||||
error: impl fmt::Display,
|
||||
) {
|
||||
self.send_from_widget_response(raw_request, FromWidgetErrorResponse::new(error))
|
||||
}
|
||||
|
||||
#[instrument(skip_all, fields(action = T::ACTION))]
|
||||
fn send_to_widget_request<T: ToWidgetRequest>(
|
||||
&mut self,
|
||||
|
||||
Reference in New Issue
Block a user