From 7c2eb31c83a202b3481a6d560ae2048bcbe4157b Mon Sep 17 00:00:00 2001 From: Akshanabha Chakraborty Date: Sun, 17 Aug 2025 20:44:16 +0530 Subject: [PATCH] feat: add `PluginHandle::run_mobile_plugin_async` (#13895) * add async * chore: fmt * feat: add run_mobile_plugin_async * changes * chore: fix misplaced `}` * chore: fix minor pattern matching error * fix: copy the response handling directly from run_mobile_plugin * fix android build * Fix clippy lint * lint --------- Co-authored-by: Lucas Nogueira --- .changes/run-mobile-plugin-async.md | 5 +++++ crates/tauri/src/plugin/mobile.rs | 34 +++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 .changes/run-mobile-plugin-async.md diff --git a/.changes/run-mobile-plugin-async.md b/.changes/run-mobile-plugin-async.md new file mode 100644 index 000000000..78d256b1e --- /dev/null +++ b/.changes/run-mobile-plugin-async.md @@ -0,0 +1,5 @@ +--- +"tauri": minor:feat +--- + +Introduces `PluginHandle::run_mobile_plugin_async` as an async alternative to `run_mobile_plugin` diff --git a/crates/tauri/src/plugin/mobile.rs b/crates/tauri/src/plugin/mobile.rs index 689be85fd..64aff828f 100644 --- a/crates/tauri/src/plugin/mobile.rs +++ b/crates/tauri/src/plugin/mobile.rs @@ -13,6 +13,8 @@ use crate::{ #[cfg(mobile)] use std::sync::atomic::{AtomicI32, Ordering}; +#[cfg(mobile)] +use tokio::sync::oneshot; use serde::{de::DeserializeOwned, Serialize}; @@ -279,6 +281,38 @@ impl PluginApi { } impl PluginHandle { + /// Executes the given mobile command. + /// This is an async optimized variant of run_mobile_plugin + pub async fn run_mobile_plugin_async( + &self, + command: impl AsRef, + payload: impl Serialize, + ) -> Result { + let (tx, rx) = oneshot::channel(); + // the closure is an FnOnce but on Android we need to clone it (error handling) + let tx = std::sync::Arc::new(std::sync::Mutex::new(Some(tx))); + run_command( + self.name, + &self.handle, + command, + serde_json::to_value(payload).map_err(PluginInvokeError::CannotSerializePayload)?, + move |response| { + tx.lock().unwrap().take().unwrap().send(response).unwrap(); + }, + )?; + + let response = rx.await.unwrap(); + + match response { + Ok(r) => serde_json::from_value(r).map_err(PluginInvokeError::CannotDeserializeResponse), + Err(r) => Err( + serde_json::from_value::(r) + .map(Into::into) + .map_err(PluginInvokeError::CannotDeserializeResponse)?, + ), + } + } + /// Executes the given mobile command. pub fn run_mobile_plugin( &self,