From 3ab75f105318c7ebf861a38c134a6c9eff33b597 Mon Sep 17 00:00:00 2001
From: Simon Laux <mobile.info@simonlaux.de>
Date: Sun, 12 Jan 2025 04:46:48 +0100
Subject: [PATCH 1/2] feat: jsonrpc: add `late_file_message_mediasize`

---
 deltachat-jsonrpc/src/api.rs               | 27 ++++++++++++++-
 deltachat-jsonrpc/src/api/types/message.rs | 39 ++++++++++++++++++++++
 2 files changed, 65 insertions(+), 1 deletion(-)

diff --git a/deltachat-jsonrpc/src/api.rs b/deltachat-jsonrpc/src/api.rs
index 5c34a554c9..8120d3ba31 100644
--- a/deltachat-jsonrpc/src/api.rs
+++ b/deltachat-jsonrpc/src/api.rs
@@ -49,7 +49,7 @@ use types::chat::FullChat;
 use types::contact::{ContactObject, VcardContact};
 use types::events::Event;
 use types::http::HttpResponse;
-use types::message::{MessageData, MessageObject, MessageReadReceipt};
+use types::message::{LateFilingMediaSize, MessageData, MessageObject, MessageReadReceipt};
 use types::provider_info::ProviderInfo;
 use types::reactions::JSONRPCReactions;
 use types::webxdc::WebxdcMessageInfo;
@@ -1262,6 +1262,31 @@ impl CommandApi {
         MsgId::new(message_id).download_full(&ctx).await
     }
 
+    /// Late filing information to a message.
+    /// Changes the message width, height or duration, and stores it into the database.
+    ///
+    /// Sometimes, the core cannot find out the width, the height or the duration
+    /// of an image, an audio or a video.
+    ///
+    /// If, in these cases, the frontend can provide the information, it can save
+    /// them together with the message object for later usage.
+    ///
+    /// This function should only be used if `Message.dimensions_width`, `Message.dimensions_height` or `Message.duration`
+    /// do not provide the expected values.
+    ///
+    /// To get the stored values later, use `Message.dimensions_width`, `Message.dimensions_height` or `Message.duration`.
+    async fn late_file_message_mediasize(
+        &self,
+        account_id: u32,
+        message_id: u32,
+        new_size: LateFilingMediaSize,
+    ) -> Result<()> {
+        let ctx = self.get_context(account_id).await?;
+        new_size
+            .apply_to_message(&ctx, MsgId::new(message_id))
+            .await
+    }
+
     /// Search messages containing the given query string.
     /// Searching can be done globally (chat_id=None) or in a specified chat only (chat_id set).
     ///
diff --git a/deltachat-jsonrpc/src/api/types/message.rs b/deltachat-jsonrpc/src/api/types/message.rs
index efe7b66ca6..35557f9416 100644
--- a/deltachat-jsonrpc/src/api/types/message.rs
+++ b/deltachat-jsonrpc/src/api/types/message.rs
@@ -712,3 +712,42 @@ impl From<deltachat::ephemeral::Timer> for EphemeralTimer {
         }
     }
 }
+
+#[derive(Deserialize, TypeDef, schemars::JsonSchema)]
+#[serde(rename_all = "camelCase")]
+pub struct LateFilingMediaSize {
+    // The new width to store in the message object. None if you don't want to change the width.
+    pub width: Option<u32>,
+    // The new height to store in the message object. None if you don't want to change the height.
+    pub height: Option<u32>,
+    // The new duration to store in the message object. None if you don't want to change it.
+    pub duration: Option<u32>,
+}
+
+impl LateFilingMediaSize {
+    pub async fn apply_to_message(
+        &self,
+        context: &Context,
+        message_id: MsgId,
+    ) -> anyhow::Result<()> {
+        let mut message = deltachat::message::Message::load_from_db(context, message_id).await?;
+        message
+            .latefiling_mediasize(
+                context,
+                self.width
+                    .unwrap_or(0)
+                    .to_i32()
+                    .context("conversion to i32 failed")?,
+                self.height
+                    .unwrap_or(0)
+                    .to_i32()
+                    .context("conversion to i32 failed")?,
+                self.duration
+                    .unwrap_or(0)
+                    .to_i32()
+                    .context("conversion to i32 failed")?,
+            )
+            .await?;
+        Ok(())
+    }
+}

From ef8b98e1aa35c4398f56512f78b26b0bed56834e Mon Sep 17 00:00:00 2001
From: Simon Laux <mobile.info@simonlaux.de>
Date: Sun, 16 Feb 2025 21:30:49 +0100
Subject: [PATCH 2/2] combine width and height into a tuple

---
 deltachat-jsonrpc/src/api/types/message.rs | 34 ++++++++++------------
 1 file changed, 15 insertions(+), 19 deletions(-)

diff --git a/deltachat-jsonrpc/src/api/types/message.rs b/deltachat-jsonrpc/src/api/types/message.rs
index 35557f9416..72e98a9c10 100644
--- a/deltachat-jsonrpc/src/api/types/message.rs
+++ b/deltachat-jsonrpc/src/api/types/message.rs
@@ -716,10 +716,8 @@ impl From<deltachat::ephemeral::Timer> for EphemeralTimer {
 #[derive(Deserialize, TypeDef, schemars::JsonSchema)]
 #[serde(rename_all = "camelCase")]
 pub struct LateFilingMediaSize {
-    // The new width to store in the message object. None if you don't want to change the width.
-    pub width: Option<u32>,
-    // The new height to store in the message object. None if you don't want to change the height.
-    pub height: Option<u32>,
+    // The new width and height to store in the message object. None if you don't want to change the dimensions.
+    pub wh: Option<(u32, u32)>,
     // The new duration to store in the message object. None if you don't want to change it.
     pub duration: Option<u32>,
 }
@@ -731,22 +729,20 @@ impl LateFilingMediaSize {
         message_id: MsgId,
     ) -> anyhow::Result<()> {
         let mut message = deltachat::message::Message::load_from_db(context, message_id).await?;
+        let (width, height) = match self.wh {
+            Some((w, h)) => (
+                w.to_i32().context("conversion to i32 failed")?,
+                h.to_i32().context("conversion to i32 failed")?,
+            ),
+            None => (0, 0),
+        };
+        let duration = self
+            .duration
+            .unwrap_or(0)
+            .to_i32()
+            .context("conversion to i32 failed")?;
         message
-            .latefiling_mediasize(
-                context,
-                self.width
-                    .unwrap_or(0)
-                    .to_i32()
-                    .context("conversion to i32 failed")?,
-                self.height
-                    .unwrap_or(0)
-                    .to_i32()
-                    .context("conversion to i32 failed")?,
-                self.duration
-                    .unwrap_or(0)
-                    .to_i32()
-                    .context("conversion to i32 failed")?,
-            )
+            .latefiling_mediasize(context, width, height, duration)
             .await?;
         Ok(())
     }