From 0ed0e109b0743b392ebe80722c84d562604661d8 Mon Sep 17 00:00:00 2001 From: "B. Petersen" Date: Sun, 14 Apr 2024 22:03:04 +0200 Subject: [PATCH] set_webxdc_integration() takes an .xdc file --- deltachat-ffi/deltachat.h | 55 ++++++++++++++-------------------- deltachat-ffi/src/lib.rs | 25 +++++++++------- src/webxdc/integration.rs | 32 ++++++++++---------- src/webxdc/maps_integration.rs | 13 +++----- 4 files changed, 57 insertions(+), 68 deletions(-) diff --git a/deltachat-ffi/deltachat.h b/deltachat-ffi/deltachat.h index 6ca18d7ccc..e18f0495a0 100644 --- a/deltachat-ffi/deltachat.h +++ b/deltachat-ffi/deltachat.h @@ -1179,6 +1179,17 @@ int dc_send_webxdc_status_update (dc_context_t* context, uint32_t msg_id, const char* dc_get_webxdc_status_updates (dc_context_t* context, uint32_t msg_id, uint32_t serial); +/** + * Set Webxdc file as integration. + * see dc_init_webxdc_integration() for more details about Webxdc integrations. + * + * @memberof dc_msg_t + * @param context The context object. + * @param file The .xdc file to use as Webxdc integration. + */ +void dc_set_webxdc_integration (dc_context_t* context, const char* file); + + /** * Init a Webxdc integration. * @@ -1199,7 +1210,17 @@ char* dc_get_webxdc_status_updates (dc_context_t* context, uint32_t msg_id, uint * There is no need to de-initialize the integration, * however, the integration is valid only as long as not re-initialized. * - * See dc_msg_set_webxdc_integration() for an example. + * Example: + * + * ~~~ + * dc_msg_set_webxdc_integration(context, path_to_maps_xdc); + * + * // Later on, you can use dc_init_webxdc_integration() to integrate the map to any chat: + * uint32_t webxdc_instance = dc_init_webxdc_integration(context, any_chat_id); + * + * // Or use it as a global map, showing locations of all chats: + * uint32_t webxdc_instance = dc_init_webxdc_integration(context, 0); + * ~~~ * * @memberof dc_context_t * @param context The context object. @@ -4709,38 +4730,6 @@ void dc_msg_set_override_sender_name(dc_msg_t* msg, const char* name) void dc_msg_set_file (dc_msg_t* msg, const char* file, const char* filemime); -/** - * Mark Webxdc message shipped with the main app as a default integration. - * Example: - * - * ~~~ - * dc_msg_t* msg = dc_msg_new(context, DC_MSG_WEBXDC); - * dc_msg_set_file(msg, path_to_maps_xdc); - * dc_msg_set_webxdc_integration(msg); - * dc_send_msg(dc_create_chat_by_contact_id(context, DC_CONTACT_ID_SELF), msg); - * ~~~ - * - * Later on, you can use dc_init_webxdc_integration() to integrate the map to any chat: - * - * ~~~ - * uint32_t webxdc_instance = dc_init_webxdc_integration(context, any_chat_id); - * ~~~ - * - * Or use it as a global map, showing locations of all chats: - * - * ~~~ - * uint32_t webxdc_instance = dc_init_webxdc_integration(context, 0); - * ~~~ - * - * The returned webxdc_instance can be used the same way as any other Webxdc. - * see dc_init_webxdc_integration() for more details about Webxdc integrations. - * - * @memberof dc_msg_t - * @param msg The Webxdc message object to mark as default integration. - */ -void dc_msg_set_webxdc_integration (dc_msg_t* msg); - - /** * Set the dimensions associated with message object. * Typically this is the width and the height of an image or video associated using dc_msg_set_file(). diff --git a/deltachat-ffi/src/lib.rs b/deltachat-ffi/src/lib.rs index 56c8830785..f38c68d262 100644 --- a/deltachat-ffi/src/lib.rs +++ b/deltachat-ffi/src/lib.rs @@ -1055,6 +1055,21 @@ pub unsafe extern "C" fn dc_get_webxdc_status_updates( .strdup() } +#[no_mangle] +pub unsafe extern "C" fn dc_msg_set_webxdc_integration( + context: *mut dc_context_t, + file: *const libc::c_char, +) { + if context.is_null() || file.is_null() { + eprintln!("ignoring careless call to dc_msg_set_webxdc_integration()"); + return; + } + let ctx = &*context; + block_on(ctx.set_webxdc_integration(to_string_lossy(file))) + .log_err(ctx) + .unwrap_or_default(); +} + #[no_mangle] pub unsafe extern "C" fn dc_init_webxdc_integration( context: *mut dc_context_t, @@ -3757,16 +3772,6 @@ pub unsafe extern "C" fn dc_msg_set_file( ) } -#[no_mangle] -pub unsafe extern "C" fn dc_msg_set_webxdc_integration(msg: *mut dc_msg_t) { - if msg.is_null() { - eprintln!("ignoring careless call to dc_msg_set_webxdc_integration()"); - return; - } - let ffi_msg = &mut *msg; - ffi_msg.message.set_webxdc_integration() -} - #[no_mangle] pub unsafe extern "C" fn dc_msg_set_dimension( msg: *mut dc_msg_t, diff --git a/src/webxdc/integration.rs b/src/webxdc/integration.rs index ea61c71fa4..61d1d6a3a3 100644 --- a/src/webxdc/integration.rs +++ b/src/webxdc/integration.rs @@ -1,20 +1,24 @@ -use crate::chat::ChatId; +use crate::chat::{send_msg, ChatId}; use crate::config::Config; +use crate::contact::ContactId; use crate::context::Context; use crate::message::{Message, MsgId, Viewtype}; use crate::param::Param; use crate::webxdc::{maps_integration, StatusUpdateItem, StatusUpdateSerial}; use anyhow::Result; -impl Message { - /// Mark Webxdc message shipped with the main app as a default integration. - pub fn set_webxdc_integration(&mut self) { - self.hidden = true; - self.param.set_int(Param::WebxdcIntegration, 1); +impl Context { + /// Set Webxdc file as integration. + pub async fn set_webxdc_integration(&self, file: String) -> Result<()> { + let chat_id = ChatId::create_for_contact(self, ContactId::SELF).await?; + let mut msg = Message::new(Viewtype::Webxdc); + msg.set_file(file.as_str(), None); + msg.hidden = true; + msg.param.set_int(Param::WebxdcIntegration, 1); + send_msg(self, chat_id, &mut msg).await?; + Ok(()) } -} -impl Context { /// Get Webxdc instance used for optional integrations. /// If there is no integration, the caller may decide to add a default one. pub async fn init_webxdc_integration( @@ -45,7 +49,7 @@ impl Context { .set_int(Param::WebxdcIntegrateFor, integrate_for); instance.update_param(self).await?; } - return Ok(Some(instance.id)); + Ok(Some(instance.id)) } // Check if a Webxdc shall be used as an integration and remember that. @@ -99,9 +103,7 @@ impl Context { #[cfg(test)] mod tests { - use crate::chat::send_msg; use crate::config::Config; - use crate::message::{Message, Viewtype}; use crate::test_utils::TestContext; use anyhow::Result; use std::time::Duration; @@ -110,14 +112,12 @@ mod tests { async fn test_default_integrations_are_single_device() -> Result<()> { let t = TestContext::new_alice().await; t.set_config_bool(Config::BccSelf, false).await?; - let chat = t.get_self_chat().await; let bytes = include_bytes!("../../test-data/webxdc/minimal.xdc"); - let mut msg = Message::new(Viewtype::Webxdc); - msg.set_file_from_bytes(&t, "my-maps.xdc", bytes, None) + let file = t.get_blobdir().join("maps.xdc"); + tokio::fs::write(&file, bytes).await.unwrap(); + t.set_webxdc_integration(file.to_str().unwrap().to_string()) .await?; - msg.set_webxdc_integration(); - send_msg(&t, chat.id, &mut msg).await?; // default integrations are shipped with the apps and should not be sent over the wire let sent = t.pop_sent_msg_opt(Duration::from_secs(1)).await; diff --git a/src/webxdc/maps_integration.rs b/src/webxdc/maps_integration.rs index ba4bd37dce..a4b9a3a1db 100644 --- a/src/webxdc/maps_integration.rs +++ b/src/webxdc/maps_integration.rs @@ -171,11 +171,10 @@ pub(crate) async fn intercept_get_updates( #[cfg(test)] mod tests { - use crate::chat::{create_group_chat, send_msg, ChatId, ProtectionStatus}; + use crate::chat::{create_group_chat, ChatId, ProtectionStatus}; use crate::chatlist::Chatlist; use crate::contact::Contact; use crate::location; - use crate::message::{Message, Viewtype}; use crate::test_utils::TestContext; use crate::webxdc::StatusUpdateSerial; use anyhow::Result; @@ -183,19 +182,15 @@ mod tests { #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn test_maps_integration() -> Result<()> { let t = TestContext::new_alice().await; - let chat = t.get_self_chat().await; let bytes = include_bytes!("../../test-data/webxdc/minimal.xdc"); - let mut msg = Message::new(Viewtype::Webxdc); - msg.set_file_from_bytes(&t, "my-maps.xdc", bytes, None) + let file = t.get_blobdir().join("maps.xdc"); + tokio::fs::write(&file, bytes).await.unwrap(); + t.set_webxdc_integration(file.to_str().unwrap().to_string()) .await?; - msg.set_webxdc_integration(); - let msg_id = send_msg(&t, chat.id, &mut msg).await?; - let msg = Message::load_from_db(&t, msg_id).await?; let chatlist = Chatlist::try_load(&t, 0, None, None).await?; let summary = chatlist.get_summary(&t, 0, None).await?; - assert!(msg.hidden); assert_eq!(summary.text, "No messages."); // Integrate Webxdc into a chat with Bob;