diff --git a/deltachat-ffi/deltachat.h b/deltachat-ffi/deltachat.h index af8cac124..5dcd263e2 100644 --- a/deltachat-ffi/deltachat.h +++ b/deltachat-ffi/deltachat.h @@ -6079,6 +6079,15 @@ void dc_event_unref(dc_event_t* event); #define DC_EVENT_MSG_READ 2015 +/** + * A single message is deleted. + * + * @param data1 (int) chat_id + * @param data2 (int) msg_id + */ +#define DC_EVENT_MSG_DELETED 2016 + + /** * Chat changed. The name or the image of a chat group was changed or members were added or removed. * Or the verify state of a chat has changed. diff --git a/deltachat-ffi/src/lib.rs b/deltachat-ffi/src/lib.rs index 320f5c23f..d35e19e04 100644 --- a/deltachat-ffi/src/lib.rs +++ b/deltachat-ffi/src/lib.rs @@ -527,6 +527,7 @@ pub unsafe extern "C" fn dc_event_get_id(event: *mut dc_event_t) -> libc::c_int EventType::MsgDelivered { .. } => 2010, EventType::MsgFailed { .. } => 2012, EventType::MsgRead { .. } => 2015, + EventType::MsgDeleted { .. } => 2016, EventType::ChatModified(_) => 2020, EventType::ChatEphemeralTimerModified { .. } => 2021, EventType::ContactsChanged(_) => 2030, @@ -574,6 +575,7 @@ pub unsafe extern "C" fn dc_event_get_data1_int(event: *mut dc_event_t) -> libc: | EventType::MsgDelivered { chat_id, .. } | EventType::MsgFailed { chat_id, .. } | EventType::MsgRead { chat_id, .. } + | EventType::MsgDeleted { chat_id, .. } | EventType::ChatModified(chat_id) | EventType::ChatEphemeralTimerModified { chat_id, .. } => chat_id.to_u32() as libc::c_int, EventType::ContactsChanged(id) | EventType::LocationChanged(id) => { @@ -631,7 +633,8 @@ pub unsafe extern "C" fn dc_event_get_data2_int(event: *mut dc_event_t) -> libc: | EventType::IncomingMsg { msg_id, .. } | EventType::MsgDelivered { msg_id, .. } | EventType::MsgFailed { msg_id, .. } - | EventType::MsgRead { msg_id, .. } => msg_id.to_u32() as libc::c_int, + | EventType::MsgRead { msg_id, .. } + | EventType::MsgDeleted { 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, @@ -674,6 +677,7 @@ pub unsafe extern "C" fn dc_event_get_data2_str(event: *mut dc_event_t) -> *mut | EventType::MsgDelivered { .. } | EventType::MsgFailed { .. } | EventType::MsgRead { .. } + | EventType::MsgDeleted { .. } | 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 892302a4f..0cfb02a84 100644 --- a/deltachat-jsonrpc/src/api/types/events.rs +++ b/deltachat-jsonrpc/src/api/types/events.rs @@ -174,6 +174,13 @@ pub enum EventType { msg_id: u32, }, + /// A single message is deleted. + #[serde(rename_all = "camelCase")] + MsgDeleted { + chat_id: u32, + msg_id: u32, + }, + /// Chat changed. The name or the image of a chat group was changed or members were added or removed. /// Or the verify state of a chat has changed. /// See setChatName(), setChatProfileImage(), addContactToChat() @@ -347,6 +354,10 @@ impl From for EventType { 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(), + }, CoreEventType::ChatModified(chat_id) => ChatModified { chat_id: chat_id.to_u32(), }, diff --git a/python/tests/test_1_online.py b/python/tests/test_1_online.py index c2df18b5a..39b9ef097 100644 --- a/python/tests/test_1_online.py +++ b/python/tests/test_1_online.py @@ -396,9 +396,12 @@ def test_forward_messages(acfactory, lp): lp.sec("ac2: check new chat has a forwarded message") assert chat3.is_promoted() messages = chat3.get_messages() + assert len(messages) == 1 msg = messages[-1] assert msg.is_forwarded() ac2.delete_messages(messages) + ev = ac2._evtracker.get_matching("DC_EVENT_MSG_DELETED") + assert ev.data2 == messages[0].id assert not chat3.get_messages() diff --git a/src/ephemeral.rs b/src/ephemeral.rs index 0ccd17d26..46922a0e4 100644 --- a/src/ephemeral.rs +++ b/src/ephemeral.rs @@ -429,7 +429,7 @@ pub(crate) async fn delete_expired_messages(context: &Context, now: i64) -> Resu if !rows.is_empty() { info!(context, "Attempting to delete {} messages.", rows.len()); - let (_msgs_changed, webxdc_deleted) = context + let (msgs_changed, webxdc_deleted) = context .sql .transaction(|transaction| { let mut msgs_changed = Vec::with_capacity(rows.len()); @@ -455,6 +455,10 @@ pub(crate) async fn delete_expired_messages(context: &Context, now: i64) -> Resu }) .await?; + for (chat_id, msg_id) in msgs_changed { + context.emit_event(EventType::MsgDeleted { chat_id, msg_id }) + } + context.emit_msgs_changed_without_ids(); for msg_id in webxdc_deleted { diff --git a/src/events/payload.rs b/src/events/payload.rs index 3820651a6..531447f2c 100644 --- a/src/events/payload.rs +++ b/src/events/payload.rs @@ -145,6 +145,27 @@ pub enum EventType { msg_id: MsgId, }, + /// A single message was deleted. + /// + /// This event means that the message will no longer appear in the messagelist. + /// UI should remove the message from the messagelist + /// in response to this event if the message is currently displayed. + /// + /// The message may have been explicitly deleted by the user or expired. + /// Internally the message may have been removed from the database, + /// moved to the trash chat or hidden. + /// + /// This event does not indicate the message + /// deletion from the server. + MsgDeleted { + /// ID of the chat where the message was prior to deletion. + /// Never 0 or trash chat. + chat_id: ChatId, + + /// ID of the deleted message. Never 0. + msg_id: MsgId, + }, + /// Chat changed. The name or the image of a chat group was changed or members were added or removed. /// Or the verify state of a chat has changed. /// See dc_set_chat_name(), dc_set_chat_profile_image(), dc_add_contact_to_chat() diff --git a/src/message.rs b/src/message.rs index 0be211e36..563f18890 100644 --- a/src/message.rs +++ b/src/message.rs @@ -1431,6 +1431,11 @@ pub async fn delete_msgs(context: &Context, msg_ids: &[MsgId]) -> Result<()> { .await .with_context(|| format!("Unable to trash message {msg_id}"))?; + context.emit_event(EventType::MsgDeleted { + chat_id: msg.chat_id, + msg_id, + }); + if msg.viewtype == Viewtype::Webxdc { context.emit_event(EventType::WebxdcInstanceDeleted { msg_id }); }