From ab03fe304084d17ece067cf9e5a56181bccbbce1 Mon Sep 17 00:00:00 2001 From: WofWca Date: Mon, 15 Jun 2026 19:34:56 +0400 Subject: [PATCH] feat: add `MsgReadCountChanged` event Useful for updating the read count on channel messages live. This supersedes https://github.com/chatmail/core/pull/7979. Unlike that MR, this one is not breaking. Needed for https://github.com/deltachat/deltachat-desktop/issues/5220. --- deltachat-ffi/deltachat.h | 9 +++++++++ deltachat-ffi/src/lib.rs | 6 +++++- deltachat-jsonrpc/src/api/types/events.rs | 15 +++++++++++++++ .../src/deltachat_rpc_client/const.py | 1 + src/events/payload.rs | 11 +++++++++++ src/mimeparser.rs | 1 + 6 files changed, 42 insertions(+), 1 deletion(-) diff --git a/deltachat-ffi/deltachat.h b/deltachat-ffi/deltachat.h index 080326b2a..8169b55f7 100644 --- a/deltachat-ffi/deltachat.h +++ b/deltachat-ffi/deltachat.h @@ -6341,6 +6341,15 @@ void dc_event_unref(dc_event_t* event); */ #define DC_EVENT_MSG_DELETED 2016 +/** + * Like @ref DC_EVENT_MSG_READ, but also fires on subsequent MDNs, + * if there are multiple receivers, i.e. in groups and channels. + * + * @param data1 (int) chat_id + * @param data2 (int) msg_id + */ +#define DC_EVENT_MSG_READ_COUNT_CHANGED 2018 + /** * Chat changed. The name or the image of a chat group was changed or members were added or removed. diff --git a/deltachat-ffi/src/lib.rs b/deltachat-ffi/src/lib.rs index 25787f35f..abea9ebba 100644 --- a/deltachat-ffi/src/lib.rs +++ b/deltachat-ffi/src/lib.rs @@ -528,6 +528,7 @@ pub unsafe extern "C" fn dc_event_get_id(event: *mut dc_event_t) -> libc::c_int EventType::MsgFailed { .. } => 2012, EventType::MsgRead { .. } => 2015, EventType::MsgDeleted { .. } => 2016, + EventType::MsgReadCountChanged { .. } => 2018, EventType::ChatModified(_) => 2020, EventType::ChatEphemeralTimerModified { .. } => 2021, EventType::ChatDeleted { .. } => 2023, @@ -602,6 +603,7 @@ pub unsafe extern "C" fn dc_event_get_data1_int(event: *mut dc_event_t) -> libc: | EventType::MsgFailed { chat_id, .. } | EventType::MsgRead { chat_id, .. } | EventType::MsgDeleted { chat_id, .. } + | EventType::MsgReadCountChanged { chat_id, .. } | EventType::ChatModified(chat_id) | EventType::ChatEphemeralTimerModified { chat_id, .. } | EventType::ChatDeleted { chat_id } => chat_id.to_u32() as libc::c_int, @@ -688,7 +690,8 @@ pub unsafe extern "C" fn dc_event_get_data2_int(event: *mut dc_event_t) -> libc: | EventType::MsgDelivered { msg_id, .. } | EventType::MsgFailed { msg_id, .. } | EventType::MsgRead { msg_id, .. } - | EventType::MsgDeleted { msg_id, .. } => msg_id.to_u32() as libc::c_int, + | EventType::MsgDeleted { msg_id, .. } + | EventType::MsgReadCountChanged { msg_id, .. } => msg_id.to_u32() as libc::c_int, EventType::SecurejoinInviterProgress { progress, .. } | EventType::SecurejoinJoinerProgress { progress, .. } => *progress as libc::c_int, EventType::ChatEphemeralTimerModified { timer, .. } => timer.to_u32() as libc::c_int, @@ -762,6 +765,7 @@ pub unsafe extern "C" fn dc_event_get_data2_str(event: *mut dc_event_t) -> *mut | EventType::MsgFailed { .. } | EventType::MsgRead { .. } | EventType::MsgDeleted { .. } + | EventType::MsgReadCountChanged { .. } | EventType::ChatModified(_) | EventType::ContactsChanged(_) | EventType::LocationChanged(_) diff --git a/deltachat-jsonrpc/src/api/types/events.rs b/deltachat-jsonrpc/src/api/types/events.rs index 85751c363..64ab1a3a4 100644 --- a/deltachat-jsonrpc/src/api/types/events.rs +++ b/deltachat-jsonrpc/src/api/types/events.rs @@ -203,6 +203,17 @@ pub enum EventType { msg_id: u32, }, + /// Like [`EventType::MsgRead`], but also fires on subsequent MDNs, + /// if there are multiple receivers, i.e. in groups and channels. + #[serde(rename_all = "camelCase")] + MsgReadCountChanged { + /// ID of the chat which the message belongs to. + chat_id: u32, + + /// ID of the message that was read. + msg_id: u32, + }, + /// A single message was deleted. /// /// This event means that the message will no longer appear in the messagelist. @@ -546,6 +557,10 @@ impl From for EventType { chat_id: chat_id.to_u32(), msg_id: msg_id.to_u32(), }, + CoreEventType::MsgReadCountChanged { chat_id, msg_id } => MsgReadCountChanged { + chat_id: chat_id.to_u32(), + msg_id: msg_id.to_u32(), + }, CoreEventType::MsgDeleted { chat_id, msg_id } => MsgDeleted { chat_id: chat_id.to_u32(), msg_id: msg_id.to_u32(), diff --git a/deltachat-rpc-client/src/deltachat_rpc_client/const.py b/deltachat-rpc-client/src/deltachat_rpc_client/const.py index d3068fe9b..e30041648 100644 --- a/deltachat-rpc-client/src/deltachat_rpc_client/const.py +++ b/deltachat-rpc-client/src/deltachat_rpc_client/const.py @@ -54,6 +54,7 @@ class EventType(str, Enum): MSG_DELIVERED = "MsgDelivered" MSG_FAILED = "MsgFailed" MSG_READ = "MsgRead" + MSG_READ_COUNT_CHANGED = "MsgReadCountChanged" MSG_DELETED = "MsgDeleted" CHAT_MODIFIED = "ChatModified" CHAT_DELETED = "ChatDeleted" diff --git a/src/events/payload.rs b/src/events/payload.rs index a008ce6d1..8300f02b1 100644 --- a/src/events/payload.rs +++ b/src/events/payload.rs @@ -181,6 +181,17 @@ pub enum EventType { msg_id: MsgId, }, + /// Like [`EventType::MsgRead`], but also fires on subsequent MDNs, + /// if there are multiple receivers, i.e. in groups and channels. + #[serde(rename_all = "camelCase")] + MsgReadCountChanged { + /// ID of the chat which the message belongs to. + chat_id: ChatId, + + /// ID of the message that was read. + msg_id: MsgId, + }, + /// A single message was deleted. /// /// This event means that the message will no longer appear in the messagelist. diff --git a/src/mimeparser.rs b/src/mimeparser.rs index ebd79f343..4b2506c76 100644 --- a/src/mimeparser.rs +++ b/src/mimeparser.rs @@ -2507,6 +2507,7 @@ async fn handle_mdn( // note(treefit): only matters if it is the last message in chat (but probably too expensive to check, debounce also solves it) chatlist_events::emit_chatlist_item_changed(context, chat_id); } + context.emit_event(EventType::MsgReadCountChanged { chat_id, msg_id }); Ok(()) }