From b93100413c113b24d8652655579682f92e68dd50 Mon Sep 17 00:00:00 2001 From: Pierre HUBERT Date: Mon, 1 Dec 2025 10:12:11 +0100 Subject: [PATCH] Propagate read receipt events --- matrixgw_backend/src/broadcast_messages.rs | 3 ++ .../src/controllers/ws_controller.rs | 35 +++++++++++++++++++ .../src/matrix_connection/sync_thread.rs | 17 ++++++++- matrixgw_frontend/src/api/WsApi.ts | 16 ++++++++- 4 files changed, 69 insertions(+), 2 deletions(-) diff --git a/matrixgw_backend/src/broadcast_messages.rs b/matrixgw_backend/src/broadcast_messages.rs index db34a75..2e129eb 100644 --- a/matrixgw_backend/src/broadcast_messages.rs +++ b/matrixgw_backend/src/broadcast_messages.rs @@ -2,6 +2,7 @@ use crate::matrix_connection::sync_thread::MatrixSyncTaskID; use crate::users::{APIToken, UserEmail}; use matrix_sdk::Room; use matrix_sdk::ruma::events::reaction::OriginalSyncReactionEvent; +use matrix_sdk::ruma::events::receipt::SyncReceiptEvent; use matrix_sdk::ruma::events::room::message::OriginalSyncRoomMessageEvent; use matrix_sdk::ruma::events::room::redaction::OriginalSyncRoomRedactionEvent; use matrix_sdk::sync::SyncResponse; @@ -32,6 +33,8 @@ pub enum BroadcastMessage { ReactionEvent(BxRoomEvent), /// New room redaction RoomRedactionEvent(BxRoomEvent), + /// Message fully read event + ReceiptEvent(BxRoomEvent), /// Raw Matrix sync response MatrixSyncResponse { user: UserEmail, sync: SyncResponse }, } diff --git a/matrixgw_backend/src/controllers/ws_controller.rs b/matrixgw_backend/src/controllers/ws_controller.rs index 0c0fab1..62553e7 100644 --- a/matrixgw_backend/src/controllers/ws_controller.rs +++ b/matrixgw_backend/src/controllers/ws_controller.rs @@ -29,6 +29,19 @@ pub struct WsRoomEvent { pub data: Box, } +#[derive(Debug, serde::Serialize)] +pub struct WsReceiptEntry { + event: OwnedEventId, + user: OwnedUserId, + ts: Option, +} + +#[derive(Debug, serde::Serialize)] +pub struct WsReceiptEvent { + pub room_id: OwnedRoomId, + pub receipts: Vec, +} + /// Messages sent to the client #[derive(Debug, serde::Serialize)] #[serde(tag = "type")] @@ -41,6 +54,9 @@ pub enum WsMessage { /// Room reaction event RoomRedactionEvent(WsRoomEvent), + + /// Fully read message event + ReceiptEvent(WsReceiptEvent), } impl WsMessage { @@ -73,6 +89,25 @@ impl WsMessage { data: Box::new(evt.data.content.clone()), })) } + BroadcastMessage::ReceiptEvent(evt) if &evt.user == user => { + let mut receipts = vec![]; + for (event_id, r) in &evt.data.content.0 { + for user_receipts in r.values() { + for (user, receipt) in user_receipts { + receipts.push(WsReceiptEntry { + event: event_id.clone(), + user: user.clone(), + ts: receipt.ts, + }) + } + } + } + + Some(Self::ReceiptEvent(WsReceiptEvent { + room_id: evt.room.room_id().to_owned(), + receipts, + })) + } _ => None, } } diff --git a/matrixgw_backend/src/matrix_connection/sync_thread.rs b/matrixgw_backend/src/matrix_connection/sync_thread.rs index 30f4307..439c753 100644 --- a/matrixgw_backend/src/matrix_connection/sync_thread.rs +++ b/matrixgw_backend/src/matrix_connection/sync_thread.rs @@ -8,6 +8,7 @@ use crate::matrix_connection::matrix_manager::MatrixManagerMsg; use futures_util::StreamExt; use matrix_sdk::Room; use matrix_sdk::ruma::events::reaction::OriginalSyncReactionEvent; +use matrix_sdk::ruma::events::receipt::SyncReceiptEvent; use matrix_sdk::ruma::events::room::message::OriginalSyncRoomMessageEvent; use matrix_sdk::ruma::events::room::redaction::OriginalSyncRoomRedactionEvent; use ractor::ActorRef; @@ -91,11 +92,25 @@ async fn sync_thread_task( room, })) { - log::warn!("Failed to forward reaction event! {e}"); + log::warn!("Failed to forward redaction event! {e}"); } }, )); + let tx_receipt_handle = tx.clone(); + let user_receipt_handle = client.email.clone(); + handlers.push( + client.add_event_handler(async move |event: SyncReceiptEvent, room: Room| { + if let Err(e) = tx_receipt_handle.send(BroadcastMessage::ReceiptEvent(BxRoomEvent { + user: user_receipt_handle.clone(), + data: Box::new(event), + room, + })) { + log::warn!("Failed to forward receipt event! {e}"); + } + }), + ); + loop { tokio::select! { // Message from tokio broadcast diff --git a/matrixgw_frontend/src/api/WsApi.ts b/matrixgw_frontend/src/api/WsApi.ts index 23eb2f3..6104170 100644 --- a/matrixgw_frontend/src/api/WsApi.ts +++ b/matrixgw_frontend/src/api/WsApi.ts @@ -45,10 +45,24 @@ export interface RoomRedactionEvent extends BaseRoomEvent { }; } +export interface ReceiptEventEntry { + event: string; + user: string; + ts?: number; +} + +export interface RoomReceiptEvent { + time: number; + type: "ReceiptEvent"; + room_id: string; + receipts: ReceiptEventEntry[]; +} + export type WsMessage = | RoomMessageEvent | RoomReactionEvent - | RoomRedactionEvent; + | RoomRedactionEvent + | RoomReceiptEvent; export class WsApi { /**