diff --git a/src/chat.rs b/src/chat.rs index 015a82000c..7c2a855a6b 100644 --- a/src/chat.rs +++ b/src/chat.rs @@ -2926,10 +2926,9 @@ pub(crate) async fn create_send_msg_jobs(context: &Context, msg: &mut Message) - let now = time(); - if rendered_msg.last_added_location_id.is_some() - && let Err(err) = location::set_kml_sent_timestamp(context, msg.chat_id, now).await - { - error!(context, "Failed to set kml sent_timestamp: {err:#}."); + if let Some(last_added_location_timestamp) = rendered_msg.last_added_location_timestamp { + location::set_kml_sent_timestamp(context, msg.chat_id, last_added_location_timestamp) + .await?; } if attach_selfavatar && let Err(err) = msg.chat_id.set_selfavatar_timestamp(context, now).await diff --git a/src/location.rs b/src/location.rs index 85ce22c386..cd575ac237 100644 --- a/src/location.rs +++ b/src/location.rs @@ -521,10 +521,9 @@ pub(crate) async fn delete_orphaned_poi(context: &Context) -> Result<()> { Ok(()) } -/// Returns `location.kml` contents. -#[expect(clippy::arithmetic_side_effects)] -pub async fn get_kml(context: &Context, chat_id: ChatId) -> Result> { - let mut last_added_location_id = 0; +/// Returns `location.kml` contents and the largest location timestamp, if any. +pub async fn get_kml(context: &Context, chat_id: ChatId) -> Result> { + let mut last_added_location_timestamp: Option = None; let self_addr = context.get_primary_self_addr().await?; @@ -540,7 +539,6 @@ pub async fn get_kml(context: &Context, chat_id: ChatId) -> Result Result=? \ - AND (timestamp>=? OR \ + AND (timestamp>? OR \ timestamp=(SELECT MAX(timestamp) FROM locations WHERE from_id=?)) \ AND independent=0 \ GROUP BY timestamp \ @@ -566,25 +564,24 @@ pub async fn get_kml(context: &Context, chat_id: ChatId) -> Result\ - {timestamp}\ + {kml_timestamp}\ {longitude},{latitude}\ \n" ); - location_count += 1; - last_added_location_id = location_id as u32; + last_added_location_timestamp = std::cmp::max(last_added_location_timestamp, Some(timestamp)); } Ok(()) }, @@ -593,8 +590,8 @@ pub async fn get_kml(context: &Context, chat_id: ChatId) -> Result 0 { - Ok(Some((ret, last_added_location_id))) + if let Some(last_added_location_timestamp) = last_added_location_timestamp { + Ok(Some((ret, last_added_location_timestamp))) } else { Ok(None) } diff --git a/src/mimefactory.rs b/src/mimefactory.rs index 7a43ec6aa4..3ee7f35920 100644 --- a/src/mimefactory.rs +++ b/src/mimefactory.rs @@ -142,7 +142,8 @@ pub struct MimeFactory { /// using `Chat-Disposition-Notification-To` header. req_mdn: bool, - last_added_location_id: Option, + /// Largest timestamp of the location sent in `location.kml` in this message. + last_added_location_timestamp: Option, /// If the created mime-structure contains sync-items, /// the IDs of these items are listed here. @@ -165,7 +166,9 @@ pub struct MimeFactory { pub struct RenderedEmail { pub message: String, pub is_encrypted: bool, - pub last_added_location_id: Option, + + /// Largest timestamp of the location sent in `location.kml` in this message. + pub last_added_location_timestamp: Option, /// A comma-separated string of sync-IDs that are used by the rendered email and must be deleted /// from `multi_device_sync` once the message is actually queued for sending. @@ -555,7 +558,7 @@ impl MimeFactory { in_reply_to, references, req_mdn, - last_added_location_id: None, + last_added_location_timestamp: None, sync_ids_to_delete: None, attach_selfavatar, webxdc_topic, @@ -606,7 +609,7 @@ impl MimeFactory { in_reply_to: String::default(), references: Vec::new(), req_mdn: false, - last_added_location_id: None, + last_added_location_timestamp: None, sync_ids_to_delete: None, attach_selfavatar: false, webxdc_topic: None, @@ -1222,7 +1225,7 @@ impl MimeFactory { }; let MimeFactory { - last_added_location_id, + last_added_location_timestamp, .. } = self; @@ -1231,7 +1234,7 @@ impl MimeFactory { Ok(RenderedEmail { message, is_encrypted, - last_added_location_id, + last_added_location_timestamp, sync_ids_to_delete: self.sync_ids_to_delete, rfc724_mid, subject: subject_str, @@ -1253,16 +1256,17 @@ impl MimeFactory { Some(part) } - /// Returns MIME part with a `location.kml` attachment. + /// Returns MIME part with a `location.kml` attachment + /// and the timestamp of the latest location timestamp. async fn get_location_kml_part( - &mut self, + &self, context: &Context, - ) -> Result>> { + ) -> Result, i64)>> { let Loaded::Message { msg, .. } = &self.loaded else { return Ok(None); }; - let Some((kml_content, last_added_location_id)) = + let Some((kml_content, last_added_location_timestamp)) = location::get_kml(context, msg.chat_id).await? else { return Ok(None); @@ -1270,11 +1274,7 @@ impl MimeFactory { let part = MimePart::new("application/vnd.google-earth.kml+xml", kml_content) .attachment("location.kml"); - if !msg.param.exists(Param::SetLatitude) { - // otherwise, the independent location is already filed - self.last_added_location_id = Some(last_added_location_id); - } - Ok(Some(part)) + Ok(Some((part, last_added_location_timestamp))) } async fn render_message( @@ -1769,14 +1769,18 @@ impl MimeFactory { } } - if let Some(msg_kml_part) = self.get_message_kml_part() { + if !matches!(self.pre_message_mode, PreMessageMode::Pre { .. }) + && let Some(msg_kml_part) = self.get_message_kml_part() + { parts.push(msg_kml_part); } - if location::is_sending_to_chat(context, msg.chat_id).await? - && let Some(part) = self.get_location_kml_part(context).await? + if !matches!(self.pre_message_mode, PreMessageMode::Pre { .. }) + && location::is_sending_to_chat(context, msg.chat_id).await? + && let Some((part, timestamp)) = self.get_location_kml_part(context).await? { parts.push(part); + self.last_added_location_timestamp = Some(timestamp); } // we do not piggyback sync-files to other self-sent-messages