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.
This commit is contained in:
iequidoo
2025-06-27 08:03:07 -03:00
committed by iequidoo
parent 2ee3675ba2
commit 3267126a33
3 changed files with 34 additions and 48 deletions

View File

@@ -466,23 +466,18 @@ pub(crate) async fn delete_expired_messages(context: &Context, now: i64) -> Resu
.transaction(|transaction| { .transaction(|transaction| {
let mut msgs_changed = Vec::with_capacity(rows.len()); let mut msgs_changed = Vec::with_capacity(rows.len());
let mut webxdc_deleted = Vec::new(); let mut webxdc_deleted = Vec::new();
// If you change which information is preserved here, also change `MsgId::trash()`
// If you change which information is removed here, also change MsgId::trash() and // and other places it references.
// which information receive_imf::add_parts() still adds to the db if the chat_id is TRASH 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 { for (msg_id, chat_id, viewtype, location_id) in rows {
transaction.execute( del_msg_stmt.execute((msg_id, DC_CHAT_ID_TRASH))?;
"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),
)?;
if location_id > 0 { if location_id > 0 {
transaction.execute( del_location_stmt.execute((location_id,))?;
"DELETE FROM locations WHERE independent=1 AND id=?",
(location_id,),
)?;
} }
msgs_changed.push((chat_id, msg_id)); msgs_changed.push((chat_id, msg_id));

View File

@@ -125,27 +125,16 @@ impl MsgId {
/// if all parts of the message are trashed with this flag. `true` if the user explicitly /// 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 /// deletes the message. As for trashing a partially downloaded message when replacing it with
/// a fully downloaded one, see `receive_imf::add_parts()`. /// a fully downloaded one, see `receive_imf::add_parts()`.
pub async fn trash(self, context: &Context, on_server: bool) -> Result<()> { pub(crate) 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 => "",
};
context context
.sql .sql
.execute( .execute(
// If you change which information is removed here, also change delete_expired_messages() and // If you change which information is preserved here, also change
// which information receive_imf::add_parts() still adds to the db if the chat_id is TRASH // `delete_expired_messages()` and which information `receive_imf::add_parts()`
&format!( // still adds to the db if chat_id is TRASH.
"UPDATE msgs SET \ "INSERT OR REPLACE INTO msgs (id, rfc724_mid, timestamp, chat_id, deleted)
chat_id=?, txt='', txt_normalized=NULL, \ SELECT ?1, rfc724_mid, timestamp, ?, ? FROM msgs WHERE id=?1",
subject='', txt_raw='', \ (self, DC_CHAT_ID_TRASH, on_server),
mime_headers='', \
from_id=0, to_id=0, \
param=''{deleted_subst} \
WHERE id=?"
),
(chat_id, self),
) )
.await?; .await?;

View File

@@ -2055,11 +2055,11 @@ RETURNING id
if trash { ContactId::UNDEFINED } else { from_id }, if trash { ContactId::UNDEFINED } else { from_id },
if trash { ContactId::UNDEFINED } else { to_id }, if trash { ContactId::UNDEFINED } else { to_id },
sort_timestamp, sort_timestamp,
mime_parser.timestamp_sent, if trash { 0 } else { mime_parser.timestamp_sent },
mime_parser.timestamp_rcvd, if trash { 0 } else { mime_parser.timestamp_rcvd },
typ, if trash { Viewtype::Unknown } else { typ },
state, if trash { MessageState::Undefined } else { state },
is_dc_message, if trash { MessengerMessage::No } else { is_dc_message },
if trash || hidden { "" } else { msg }, if trash || hidden { "" } else { msg },
if trash || hidden { None } else { message::normalize_text(msg) }, if trash || hidden { None } else { message::normalize_text(msg) },
if trash || hidden { "" } else { &subject }, if trash || hidden { "" } else { &subject },
@@ -2068,27 +2068,29 @@ RETURNING id
} else { } else {
param.to_string() param.to_string()
}, },
hidden, !trash && hidden,
part.bytes as isize, if trash { 0 } else { part.bytes as isize },
if save_mime_modified && !(trash || hidden) { if save_mime_modified && !(trash || hidden) {
mime_headers.clone() mime_headers.clone()
} else { } else {
Vec::new() Vec::new()
}, },
mime_in_reply_to, if trash { "" } else { mime_in_reply_to },
mime_references, if trash { "" } else { mime_references },
save_mime_modified, !trash && save_mime_modified,
part.error.as_deref().unwrap_or_default(), if trash { "" } else { part.error.as_deref().unwrap_or_default() },
ephemeral_timer, if trash { 0 } else { ephemeral_timer.to_u32() },
ephemeral_timestamp, if trash { 0 } else { ephemeral_timestamp },
if is_partial_download.is_some() { if trash {
DownloadState::Done
} else if is_partial_download.is_some() {
DownloadState::Available DownloadState::Available
} else if mime_parser.decrypting_failed { } else if mime_parser.decrypting_failed {
DownloadState::Undecipherable DownloadState::Undecipherable
} else { } else {
DownloadState::Done DownloadState::Done
}, },
mime_parser.hop_info if trash { "" } else { &mime_parser.hop_info },
], ],
|row| { |row| {
let msg_id: MsgId = row.get(0)?; let msg_id: MsgId = row.get(0)?;