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| {
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));

View File

@@ -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?;

View File

@@ -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)?;