From 3267126a334c89cc1027132465f965b16737f68e Mon Sep 17 00:00:00 2001 From: iequidoo Date: Fri, 27 Jun 2025 08:03:07 -0300 Subject: [PATCH] feat: Preserve minimum info for trashed messages + Make `MsgId::trash()` `pub(crate)`, not public. + In `delete_expired_messages()`, prepare SQL statements to be executed in a loop. --- src/ephemeral.rs | 25 ++++++++++--------------- src/message.rs | 25 +++++++------------------ src/receive_imf.rs | 32 +++++++++++++++++--------------- 3 files changed, 34 insertions(+), 48 deletions(-) diff --git a/src/ephemeral.rs b/src/ephemeral.rs index 45c71cb1a..291bb1bef 100644 --- a/src/ephemeral.rs +++ b/src/ephemeral.rs @@ -466,23 +466,18 @@ pub(crate) async fn delete_expired_messages(context: &Context, now: i64) -> Resu .transaction(|transaction| { let mut msgs_changed = Vec::with_capacity(rows.len()); let mut webxdc_deleted = Vec::new(); - - // If you change which information is removed here, also change MsgId::trash() and - // which information receive_imf::add_parts() still adds to the db if the chat_id is TRASH + // If you change which information is preserved here, also change `MsgId::trash()` + // and other places it references. + let mut del_msg_stmt = transaction.prepare( + "INSERT OR REPLACE INTO msgs (id, rfc724_mid, timestamp, chat_id) + SELECT ?1, rfc724_mid, timestamp, ? FROM msgs WHERE id=?1", + )?; + let mut del_location_stmt = + transaction.prepare("DELETE FROM locations WHERE independent=1 AND id=?")?; for (msg_id, chat_id, viewtype, location_id) in rows { - transaction.execute( - "UPDATE msgs - SET chat_id=?, txt='', txt_normalized=NULL, subject='', txt_raw='', - mime_headers='', from_id=0, to_id=0, param='' - WHERE id=?", - (DC_CHAT_ID_TRASH, msg_id), - )?; - + del_msg_stmt.execute((msg_id, DC_CHAT_ID_TRASH))?; if location_id > 0 { - transaction.execute( - "DELETE FROM locations WHERE independent=1 AND id=?", - (location_id,), - )?; + del_location_stmt.execute((location_id,))?; } msgs_changed.push((chat_id, msg_id)); diff --git a/src/message.rs b/src/message.rs index f9db4b2ae..5cbb42e68 100644 --- a/src/message.rs +++ b/src/message.rs @@ -125,27 +125,16 @@ impl MsgId { /// if all parts of the message are trashed with this flag. `true` if the user explicitly /// deletes the message. As for trashing a partially downloaded message when replacing it with /// a fully downloaded one, see `receive_imf::add_parts()`. - pub async fn trash(self, context: &Context, on_server: bool) -> Result<()> { - let chat_id = DC_CHAT_ID_TRASH; - let deleted_subst = match on_server { - true => ", deleted=1", - false => "", - }; + pub(crate) async fn trash(self, context: &Context, on_server: bool) -> Result<()> { context .sql .execute( - // If you change which information is removed here, also change delete_expired_messages() and - // which information receive_imf::add_parts() still adds to the db if the chat_id is TRASH - &format!( - "UPDATE msgs SET \ - chat_id=?, txt='', txt_normalized=NULL, \ - subject='', txt_raw='', \ - mime_headers='', \ - from_id=0, to_id=0, \ - param=''{deleted_subst} \ - WHERE id=?" - ), - (chat_id, self), + // If you change which information is preserved here, also change + // `delete_expired_messages()` and which information `receive_imf::add_parts()` + // still adds to the db if chat_id is TRASH. + "INSERT OR REPLACE INTO msgs (id, rfc724_mid, timestamp, chat_id, deleted) + SELECT ?1, rfc724_mid, timestamp, ?, ? FROM msgs WHERE id=?1", + (self, DC_CHAT_ID_TRASH, on_server), ) .await?; diff --git a/src/receive_imf.rs b/src/receive_imf.rs index e1c2f8dc0..c6a517429 100644 --- a/src/receive_imf.rs +++ b/src/receive_imf.rs @@ -2055,11 +2055,11 @@ RETURNING id if trash { ContactId::UNDEFINED } else { from_id }, if trash { ContactId::UNDEFINED } else { to_id }, sort_timestamp, - mime_parser.timestamp_sent, - mime_parser.timestamp_rcvd, - typ, - state, - is_dc_message, + if trash { 0 } else { mime_parser.timestamp_sent }, + if trash { 0 } else { mime_parser.timestamp_rcvd }, + if trash { Viewtype::Unknown } else { typ }, + if trash { MessageState::Undefined } else { state }, + if trash { MessengerMessage::No } else { is_dc_message }, if trash || hidden { "" } else { msg }, if trash || hidden { None } else { message::normalize_text(msg) }, if trash || hidden { "" } else { &subject }, @@ -2068,27 +2068,29 @@ RETURNING id } else { param.to_string() }, - hidden, - part.bytes as isize, + !trash && hidden, + if trash { 0 } else { part.bytes as isize }, if save_mime_modified && !(trash || hidden) { mime_headers.clone() } else { Vec::new() }, - mime_in_reply_to, - mime_references, - save_mime_modified, - part.error.as_deref().unwrap_or_default(), - ephemeral_timer, - ephemeral_timestamp, - if is_partial_download.is_some() { + if trash { "" } else { mime_in_reply_to }, + if trash { "" } else { mime_references }, + !trash && save_mime_modified, + if trash { "" } else { part.error.as_deref().unwrap_or_default() }, + if trash { 0 } else { ephemeral_timer.to_u32() }, + if trash { 0 } else { ephemeral_timestamp }, + if trash { + DownloadState::Done + } else if is_partial_download.is_some() { DownloadState::Available } else if mime_parser.decrypting_failed { DownloadState::Undecipherable } else { DownloadState::Done }, - mime_parser.hop_info + if trash { "" } else { &mime_parser.hop_info }, ], |row| { let msg_id: MsgId = row.get(0)?;