From 253362899bd7c7e8b8333689a34deba92ea3a420 Mon Sep 17 00:00:00 2001 From: iequidoo Date: Tue, 10 Dec 2024 15:33:30 -0300 Subject: [PATCH] feat: Set `mime_modified` for the last message part, not the first (#4462) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Otherwise the "Show Full Message..." button appears somewhere in the middle of the multipart message, e.g. after a text in the first message bubble, but before a text in the second bubble. Moreover, if the second/n-th bubble's text is shortened (ends with "[...]"), the user should scroll up to click on "Show Full Message..." which doesn't look reasonable. Scrolling down looks more acceptable (e.g. if the first bubble's text is shortened in a multipart message). I'd even suggest to show somehow that message bubbles belong to the same multipart message, e.g. add "[↵]" to the text of all bubbles except the last one, but let's discuss this first. --- src/mimeparser.rs | 10 ++++------ src/receive_imf.rs | 26 ++++++++++++-------------- 2 files changed, 16 insertions(+), 20 deletions(-) diff --git a/src/mimeparser.rs b/src/mimeparser.rs index 42f4fda54..4eb80b4d9 100644 --- a/src/mimeparser.rs +++ b/src/mimeparser.rs @@ -105,14 +105,12 @@ pub(crate) struct MimeMessage { /// received. pub(crate) footer: Option, - // if this flag is set, the parts/text/etc. are just close to the original mime-message; - // clients should offer a way to view the original message in this case + /// If set, this is a modified MIME message; clients should offer a way to view the original + /// MIME message in this case. pub is_mime_modified: bool, - /// The decrypted, raw mime structure. - /// - /// This is non-empty iff `is_mime_modified` and the message was actually encrypted. It is used - /// for e.g. late-parsing HTML. + /// Decrypted, raw MIME structure. Nonempty iff `is_mime_modified` and the message was actually + /// encrypted. pub decoded_data: Vec, /// Hop info for debugging. diff --git a/src/receive_imf.rs b/src/receive_imf.rs index 12a776750..439731e9b 100644 --- a/src/receive_imf.rs +++ b/src/receive_imf.rs @@ -1406,10 +1406,11 @@ async fn add_parts( // we save the full mime-message and add a flag // that the ui should show button to display the full message. - // a flag used to avoid adding "show full message" button to multiple parts of the message. - let mut save_mime_modified = mime_parser.is_mime_modified; + // We add "Show Full Message" button to the last message bubble (part) if this flag evaluates to + // `true` finally. + let mut save_mime_modified = false; - let mime_headers = if save_mime_headers || save_mime_modified { + let mime_headers = if save_mime_headers || mime_parser.is_mime_modified { let headers = if !mime_parser.decoded_data.is_empty() { mime_parser.decoded_data.clone() } else { @@ -1475,7 +1476,8 @@ async fn add_parts( } } - for part in &mime_parser.parts { + let mut parts = mime_parser.parts.iter().peekable(); + while let Some(part) = parts.next() { if part.is_reaction { let reaction_str = simplify::remove_footers(part.msg.as_str()); let is_incoming_fresh = mime_parser.incoming && !seen && !fetching_existing_messages; @@ -1519,14 +1521,11 @@ async fn add_parts( } else { (&part.msg, part.typ) }; - let part_is_empty = typ == Viewtype::Text && msg.is_empty() && part.param.get(Param::Quote).is_none(); - let mime_modified = save_mime_modified && !part_is_empty; - if mime_modified { - // Avoid setting mime_modified for more than one part. - save_mime_modified = false; - } + + save_mime_modified |= mime_parser.is_mime_modified && !part_is_empty && !hidden; + let save_mime_modified = save_mime_modified && parts.peek().is_none(); if part.typ == Viewtype::Text { let msg_raw = part.msg_raw.as_ref().cloned().unwrap_or_default(); @@ -1546,8 +1545,7 @@ async fn add_parts( // If you change which information is skipped if the message is trashed, // also change `MsgId::trash()` and `delete_expired_messages()` - let trash = - chat_id.is_trash() || (is_location_kml && msg.is_empty() && typ == Viewtype::Text); + let trash = chat_id.is_trash() || (is_location_kml && part_is_empty && !save_mime_modified); let row_id = context .sql @@ -1610,14 +1608,14 @@ RETURNING id }, hidden, part.bytes as isize, - if (save_mime_headers || mime_modified) && !trash { + if (save_mime_headers || save_mime_modified) && !trash { mime_headers.clone() } else { Vec::new() }, mime_in_reply_to, mime_references, - mime_modified, + save_mime_modified, part.error.as_deref().unwrap_or_default(), ephemeral_timer, ephemeral_timestamp,