From fdcaf935fa75ecfa2806939c4faad4fe9e880386 Mon Sep 17 00:00:00 2001 From: Lucas Fernandes Nogueira Date: Thu, 22 Feb 2024 08:52:27 -0300 Subject: [PATCH] feat(webview): add reparent API (#8939) * feat(webview): add reparent API * fix build * fix import * remove cfg * fix windows * clone * clone value * () --- .changes/reparent.md | 8 + core/tauri-runtime-wry/src/lib.rs | 410 +++++++++++------- core/tauri-runtime/src/lib.rs | 3 + core/tauri/build.rs | 1 + .../webview/autogenerated/reference.md | 8 + core/tauri/scripts/bundle.global.js | 2 +- core/tauri/src/ipc/protocol.rs | 6 +- core/tauri/src/test/mock_runtime.rs | 4 + core/tauri/src/webview/mod.rs | 77 ++-- core/tauri/src/webview/plugin.rs | 14 + core/tauri/src/webview/webview_window.rs | 12 +- core/tauri/src/window/mod.rs | 4 +- tooling/api/src/webview.ts | 18 + 13 files changed, 368 insertions(+), 199 deletions(-) create mode 100644 .changes/reparent.md diff --git a/.changes/reparent.md b/.changes/reparent.md new file mode 100644 index 000000000..318162aa5 --- /dev/null +++ b/.changes/reparent.md @@ -0,0 +1,8 @@ +--- +"@tauri-apps/api": patch:feat +"tauri": patch:feat +"tauri-runtime": patch:feat +"tauri-runtime-wry": patch:feat +--- + +Added the `reparent` function to the webview API. diff --git a/core/tauri-runtime-wry/src/lib.rs b/core/tauri-runtime-wry/src/lib.rs index f8f8407bb..b877a3dc7 100644 --- a/core/tauri-runtime-wry/src/lib.rs +++ b/core/tauri-runtime-wry/src/lib.rs @@ -170,7 +170,11 @@ macro_rules! webview_getter { getter!( $self, rx, - Message::Webview($self.window_id, $self.webview_id, $message(tx)) + Message::Webview( + *$self.window_id.lock().unwrap(), + $self.webview_id, + $message(tx) + ) ) }}; } @@ -280,7 +284,7 @@ impl Context { let detached_webview = webview_id.map(|id| DetachedWebview { label: label.clone(), dispatcher: WryWebviewDispatcher { - window_id, + window_id: Arc::new(Mutex::new(window_id)), webview_id: id, context: self.clone(), }, @@ -304,6 +308,9 @@ impl Context { let webview_id = self.next_webview_id(); + let window_id_wrapper = Arc::new(Mutex::new(window_id)); + let window_id_wrapper_ = window_id_wrapper.clone(); + send_user_message( self, Message::CreateWebview( @@ -312,7 +319,7 @@ impl Context { create_webview( WebviewKind::WindowChild, window, - window_id, + window_id_wrapper_, webview_id, &context, pending, @@ -322,7 +329,7 @@ impl Context { )?; let dispatcher = WryWebviewDispatcher { - window_id, + window_id: window_id_wrapper, webview_id, context: self.clone(), }; @@ -1170,6 +1177,7 @@ pub enum WebviewMessage { SetPosition(Position), SetSize(Size), SetFocus, + Reparent(WindowId), // Getters Url(Sender), Position(Sender>), @@ -1220,7 +1228,7 @@ impl Clone for Message { /// The Tauri [`WebviewDispatch`] for [`Wry`]. #[derive(Debug, Clone)] pub struct WryWebviewDispatcher { - window_id: WindowId, + window_id: Arc>, webview_id: WebviewId, context: Context, } @@ -1235,7 +1243,7 @@ impl WebviewDispatch for WryWebviewDispatcher { fn on_webview_event(&self, f: F) -> WindowEventId { let id = self.context.next_webview_event_id(); let _ = self.context.proxy.send_event(Message::Webview( - self.window_id, + *self.window_id.lock().unwrap(), self.webview_id, WebviewMessage::AddEventListener(id, Box::new(f)), )); @@ -1246,7 +1254,7 @@ impl WebviewDispatch for WryWebviewDispatcher { send_user_message( &self.context, Message::Webview( - self.window_id, + *self.window_id.lock().unwrap(), self.webview_id, WebviewMessage::WithWebview(Box::new(move |webview| f(Box::new(webview)))), ), @@ -1258,7 +1266,7 @@ impl WebviewDispatch for WryWebviewDispatcher { let _ = send_user_message( &self.context, Message::Webview( - self.window_id, + *self.window_id.lock().unwrap(), self.webview_id, WebviewMessage::OpenDevTools, ), @@ -1270,7 +1278,7 @@ impl WebviewDispatch for WryWebviewDispatcher { let _ = send_user_message( &self.context, Message::Webview( - self.window_id, + *self.window_id.lock().unwrap(), self.webview_id, WebviewMessage::CloseDevTools, ), @@ -1303,7 +1311,7 @@ impl WebviewDispatch for WryWebviewDispatcher { send_user_message( &self.context, Message::Webview( - self.window_id, + *self.window_id.lock().unwrap(), self.webview_id, WebviewMessage::Navigate(url), ), @@ -1313,14 +1321,22 @@ impl WebviewDispatch for WryWebviewDispatcher { fn print(&self) -> Result<()> { send_user_message( &self.context, - Message::Webview(self.window_id, self.webview_id, WebviewMessage::Print), + Message::Webview( + *self.window_id.lock().unwrap(), + self.webview_id, + WebviewMessage::Print, + ), ) } fn close(&self) -> Result<()> { send_user_message( &self.context, - Message::Webview(self.window_id, self.webview_id, WebviewMessage::Close), + Message::Webview( + *self.window_id.lock().unwrap(), + self.webview_id, + WebviewMessage::Close, + ), ) } @@ -1328,7 +1344,7 @@ impl WebviewDispatch for WryWebviewDispatcher { send_user_message( &self.context, Message::Webview( - self.window_id, + *self.window_id.lock().unwrap(), self.webview_id, WebviewMessage::SetSize(size), ), @@ -1339,7 +1355,7 @@ impl WebviewDispatch for WryWebviewDispatcher { send_user_message( &self.context, Message::Webview( - self.window_id, + *self.window_id.lock().unwrap(), self.webview_id, WebviewMessage::SetPosition(position), ), @@ -1349,10 +1365,29 @@ impl WebviewDispatch for WryWebviewDispatcher { fn set_focus(&self) -> Result<()> { send_user_message( &self.context, - Message::Webview(self.window_id, self.webview_id, WebviewMessage::SetFocus), + Message::Webview( + *self.window_id.lock().unwrap(), + self.webview_id, + WebviewMessage::SetFocus, + ), ) } + fn reparent(&self, window_id: WindowId) -> Result<()> { + let mut current_window_id = self.window_id.lock().unwrap(); + send_user_message( + &self.context, + Message::Webview( + *current_window_id, + self.webview_id, + WebviewMessage::Reparent(window_id), + ), + )?; + + *current_window_id = window_id; + Ok(()) + } + #[cfg(all(feature = "tracing", not(target_os = "android")))] fn eval_script>(&self, script: S) -> Result<()> { // use a channel so the EvaluateScript task uses the current span as parent @@ -1361,7 +1396,7 @@ impl WebviewDispatch for WryWebviewDispatcher { self, rx, Message::Webview( - self.window_id, + *self.window_id.lock().unwrap(), self.webview_id, WebviewMessage::EvaluateScript(script.into(), tx, tracing::Span::current()), ) @@ -1373,7 +1408,7 @@ impl WebviewDispatch for WryWebviewDispatcher { send_user_message( &self.context, Message::Webview( - self.window_id, + *self.window_id.lock().unwrap(), self.webview_id, WebviewMessage::EvaluateScript(script.into()), ), @@ -2235,7 +2270,7 @@ impl Runtime for Wry { let detached_webview = webview_id.map(|id| DetachedWebview { label: label.clone(), dispatcher: WryWebviewDispatcher { - window_id, + window_id: Arc::new(Mutex::new(window_id)), webview_id: id, context: self.context.clone(), }, @@ -2265,12 +2300,14 @@ impl Runtime for Wry { .get(&window_id) .and_then(|w| w.inner.clone()); if let Some(window) = window { + let window_id_wrapper = Arc::new(Mutex::new(window_id)); + let webview_id = self.context.next_webview_id(); let webview = create_webview( WebviewKind::WindowChild, &window, - window_id, + window_id_wrapper.clone(), webview_id, &self.context, pending, @@ -2290,7 +2327,7 @@ impl Runtime for Wry { }); let dispatcher = WryWebviewDispatcher { - window_id, + window_id: window_id_wrapper, webview_id, context: self.context.clone(), }; @@ -2685,87 +2722,33 @@ fn handle_user_message( } } } - Message::Webview(window_id, webview_id, webview_message) => { - let webview_handle = windows.0.borrow().get(&window_id).map(|w| { - ( - w.inner.clone(), - w.webviews.iter().find(|w| w.id == webview_id).cloned(), - ) - }); - if let Some((Some(window), Some(webview))) = webview_handle { - match webview_message { - WebviewMessage::WebviewEvent(_) => { /* already handled */ } - WebviewMessage::SynthesizedWindowEvent(_) => { /* already handled */ } + if let WebviewMessage::Reparent(new_parent_window_id) = webview_message { + let webview_handle = windows.0.borrow_mut().get_mut(&window_id).and_then(|w| { + w.webviews + .iter() + .position(|w| w.id == webview_id) + .map(|webview_index| w.webviews.remove(webview_index)) + }); - WebviewMessage::AddEventListener(id, listener) => { - webview - .webview_event_listeners - .lock() - .unwrap() - .insert(id, listener); - } - - #[cfg(all(feature = "tracing", not(target_os = "android")))] - WebviewMessage::EvaluateScript(script, tx, span) => { - let _span = span.entered(); - if let Err(e) = webview.evaluate_script(&script) { - debug_eprintln!("{}", e); + if let Some(webview) = webview_handle { + if let Some((Some(new_parent_window), new_parent_window_webviews)) = windows + .0 + .borrow_mut() + .get_mut(&new_parent_window_id) + .map(|w| (w.inner.clone(), &mut w.webviews)) + { + #[cfg(target_os = "macos")] + { + use wry::WebViewExtMacOS; + webview.inner.reparent(new_parent_window.ns_window() as _); + new_parent_window_webviews.push(webview); } - tx.send(()).unwrap(); - } - #[cfg(not(all(feature = "tracing", not(target_os = "android"))))] - WebviewMessage::EvaluateScript(script) => { - if let Err(e) = webview.evaluate_script(&script) { - debug_eprintln!("{}", e); + #[cfg(windows)] + { + webview.inner.reparent(new_parent_window.hwnd()); + new_parent_window_webviews.push(webview); } - } - WebviewMessage::Navigate(url) => webview.load_url(url.as_str()), - WebviewMessage::Print => { - let _ = webview.print(); - } - WebviewMessage::Close => { - windows.0.borrow_mut().get_mut(&window_id).map(|window| { - if let Some(i) = window.webviews.iter().position(|w| w.id == webview.id) { - window.webviews.remove(i); - } - window - }); - } - WebviewMessage::SetSize(size) => { - let mut bounds = webview.bounds(); - let size = size.to_logical(window.scale_factor()); - bounds.width = size.width; - bounds.height = size.height; - - if let Some(b) = &webview.bounds { - let window_size = window.inner_size(); - let mut bounds = b.lock().unwrap(); - bounds.width_rate = size.width as f32 / window_size.width as f32; - bounds.height_rate = size.height as f32 / window_size.height as f32; - } - - webview.set_bounds(bounds); - } - WebviewMessage::SetPosition(position) => { - let mut bounds = webview.bounds(); - let position = position.to_logical(window.scale_factor()); - bounds.x = position.x; - bounds.y = position.y; - - if let Some(b) = &webview.bounds { - let window_size = window.inner_size(); - let mut bounds = b.lock().unwrap(); - bounds.width_rate = position.x as f32 / window_size.width as f32; - bounds.height_rate = position.y as f32 / window_size.height as f32; - } - - webview.set_bounds(bounds); - } - WebviewMessage::SetFocus => { - webview.focus(); - } - WebviewMessage::WithWebview(f) => { #[cfg(any( target_os = "linux", target_os = "dragonfly", @@ -2774,68 +2757,163 @@ fn handle_user_message( target_os = "openbsd" ))] { - f(webview.webview()); + if let Some(container) = new_parent_window.default_vbox() { + webview.inner.reparent(container); + new_parent_window_webviews.push(webview); + } } - #[cfg(target_os = "macos")] - { - use wry::WebViewExtMacOS; - f(Webview { - webview: webview.webview(), - manager: webview.manager(), - ns_window: webview.ns_window(), + } + } + } else { + let webview_handle = windows.0.borrow().get(&window_id).map(|w| { + ( + w.inner.clone(), + w.webviews.iter().find(|w| w.id == webview_id).cloned(), + ) + }); + if let Some((Some(window), Some(webview))) = webview_handle { + match webview_message { + WebviewMessage::WebviewEvent(_) => { /* already handled */ } + WebviewMessage::SynthesizedWindowEvent(_) => { /* already handled */ } + WebviewMessage::Reparent(_window_id) => { /* already handled */ } + WebviewMessage::AddEventListener(id, listener) => { + webview + .webview_event_listeners + .lock() + .unwrap() + .insert(id, listener); + } + + #[cfg(all(feature = "tracing", not(target_os = "android")))] + WebviewMessage::EvaluateScript(script, tx, span) => { + let _span = span.entered(); + if let Err(e) = webview.evaluate_script(&script) { + debug_eprintln!("{}", e); + } + tx.send(()).unwrap(); + } + #[cfg(not(all(feature = "tracing", not(target_os = "android"))))] + WebviewMessage::EvaluateScript(script) => { + if let Err(e) = webview.evaluate_script(&script) { + debug_eprintln!("{}", e); + } + } + WebviewMessage::Navigate(url) => webview.load_url(url.as_str()), + WebviewMessage::Print => { + let _ = webview.print(); + } + WebviewMessage::Close => { + windows.0.borrow_mut().get_mut(&window_id).map(|window| { + if let Some(i) = window.webviews.iter().position(|w| w.id == webview.id) { + window.webviews.remove(i); + } + window }); } - #[cfg(target_os = "ios")] - { - use tao::platform::ios::WindowExtIOS; - use wry::WebViewExtIOS; + WebviewMessage::SetSize(size) => { + let mut bounds = webview.bounds(); + let size = size.to_logical(window.scale_factor()); + bounds.width = size.width; + bounds.height = size.height; - f(Webview { - webview: webview.inner.webview(), - manager: webview.inner.manager(), - view_controller: window.ui_view_controller() as cocoa::base::id, - }); - } - #[cfg(windows)] - { - f(Webview { - controller: webview.controller(), - }); - } - #[cfg(target_os = "android")] - { - f(webview.handle()) - } - } + if let Some(b) = &webview.bounds { + let window_size = window.inner_size(); + let mut bounds = b.lock().unwrap(); + bounds.width_rate = size.width as f32 / window_size.width as f32; + bounds.height_rate = size.height as f32 / window_size.height as f32; + } - #[cfg(any(debug_assertions, feature = "devtools"))] - WebviewMessage::OpenDevTools => { - webview.open_devtools(); - } - #[cfg(any(debug_assertions, feature = "devtools"))] - WebviewMessage::CloseDevTools => { - webview.close_devtools(); - } - #[cfg(any(debug_assertions, feature = "devtools"))] - WebviewMessage::IsDevToolsOpen(tx) => { - tx.send(webview.is_devtools_open()).unwrap(); - } + webview.set_bounds(bounds); + } + WebviewMessage::SetPosition(position) => { + let mut bounds = webview.bounds(); + let position = position.to_logical(window.scale_factor()); + bounds.x = position.x; + bounds.y = position.y; - // Getters - WebviewMessage::Url(tx) => { - tx.send(webview.url().parse().unwrap()).unwrap(); - } - WebviewMessage::Position(tx) => { - let bounds = webview.bounds(); - let position = - LogicalPosition::new(bounds.x, bounds.y).to_physical(window.scale_factor()); - tx.send(position).unwrap(); - } - WebviewMessage::Size(tx) => { - let bounds = webview.bounds(); - let size = - LogicalSize::new(bounds.width, bounds.height).to_physical(window.scale_factor()); - tx.send(size).unwrap(); + if let Some(b) = &webview.bounds { + let window_size = window.inner_size(); + let mut bounds = b.lock().unwrap(); + bounds.width_rate = position.x as f32 / window_size.width as f32; + bounds.height_rate = position.y as f32 / window_size.height as f32; + } + + webview.set_bounds(bounds); + } + // Getters + WebviewMessage::Url(tx) => { + tx.send(webview.url().parse().unwrap()).unwrap(); + } + WebviewMessage::Position(tx) => { + let bounds = webview.bounds(); + let position = + LogicalPosition::new(bounds.x, bounds.y).to_physical(window.scale_factor()); + tx.send(position).unwrap(); + } + WebviewMessage::Size(tx) => { + let bounds = webview.bounds(); + let size = + LogicalSize::new(bounds.width, bounds.height).to_physical(window.scale_factor()); + tx.send(size).unwrap(); + } + WebviewMessage::SetFocus => { + webview.focus(); + } + WebviewMessage::WithWebview(f) => { + #[cfg(any( + target_os = "linux", + target_os = "dragonfly", + target_os = "freebsd", + target_os = "netbsd", + target_os = "openbsd" + ))] + { + f(webview.webview()); + } + #[cfg(target_os = "macos")] + { + use wry::WebViewExtMacOS; + f(Webview { + webview: webview.webview(), + manager: webview.manager(), + ns_window: webview.ns_window(), + }); + } + #[cfg(target_os = "ios")] + { + use tao::platform::ios::WindowExtIOS; + use wry::WebViewExtIOS; + + f(Webview { + webview: webview.inner.webview(), + manager: webview.inner.manager(), + view_controller: window.ui_view_controller() as cocoa::base::id, + }); + } + #[cfg(windows)] + { + f(Webview { + controller: webview.controller(), + }); + } + #[cfg(target_os = "android")] + { + f(webview.handle()) + } + } + + #[cfg(any(debug_assertions, feature = "devtools"))] + WebviewMessage::OpenDevTools => { + webview.open_devtools(); + } + #[cfg(any(debug_assertions, feature = "devtools"))] + WebviewMessage::CloseDevTools => { + webview.close_devtools(); + } + #[cfg(any(debug_assertions, feature = "devtools"))] + WebviewMessage::IsDevToolsOpen(tx) => { + tx.send(webview.is_devtools_open()).unwrap(); + } } } } @@ -3341,7 +3419,7 @@ fn create_window( webviews.push(create_webview( WebviewKind::WindowContent, &window, - window_id, + Arc::new(Mutex::new(window_id)), webview_id, context, webview, @@ -3390,7 +3468,7 @@ enum WebviewKind { WindowChild, } -#[derive(Clone)] +#[derive(Debug, Clone)] struct WebviewBounds { x_rate: f32, y_rate: f32, @@ -3401,7 +3479,7 @@ struct WebviewBounds { fn create_webview( kind: WebviewKind, window: &Window, - window_id: WindowId, + window_id: Arc>, id: WebviewId, context: &Context, pending: PendingWebview>, @@ -3470,6 +3548,7 @@ fn create_webview( if webview_attributes.file_drop_handler_enabled { let proxy = context.proxy.clone(); + let window_id_ = window_id.clone(); webview_builder = webview_builder.with_file_drop_handler(move |event| { let event = match event { WryFileDropEvent::Hovered { @@ -3496,7 +3575,7 @@ fn create_webview( WebviewMessage::WebviewEvent(WebviewEvent::FileDrop(event)) }; - let _ = proxy.send_event(Message::Webview(window_id, id, message)); + let _ = proxy.send_event(Message::Webview(*window_id_.lock().unwrap(), id, message)); true }); } @@ -3598,7 +3677,7 @@ fn create_webview( webview_builder = webview_builder.with_ipc_handler(create_ipc_handler( kind, - window_id, + window_id.clone(), id, context.clone(), label.clone(), @@ -3696,12 +3775,13 @@ fn create_webview( let controller = webview.controller(); let proxy = context.proxy.clone(); let proxy_ = proxy.clone(); + let window_id_ = window_id.clone(); let mut token = EventRegistrationToken::default(); unsafe { controller.add_GotFocus( &FocusChangedEventHandler::create(Box::new(move |_, _| { - let _ = proxy_.send_event(Message::Webview( - window_id, + let _ = proxy.send_event(Message::Webview( + *window_id_.lock().unwrap(), id, WebviewMessage::SynthesizedWindowEvent(SynthesizedWindowEvent::Focused(true)), )); @@ -3714,8 +3794,8 @@ fn create_webview( unsafe { controller.add_LostFocus( &FocusChangedEventHandler::create(Box::new(move |_, _| { - let _ = proxy.send_event(Message::Webview( - window_id, + let _ = proxy_.send_event(Message::Webview( + *window_id.lock().unwrap(), id, WebviewMessage::SynthesizedWindowEvent(SynthesizedWindowEvent::Focused(false)), )); @@ -3745,7 +3825,7 @@ fn create_webview( /// Create a wry ipc handler from a tauri ipc handler. fn create_ipc_handler( _kind: WebviewKind, - window_id: WindowId, + window_id: Arc>, webview_id: WebviewId, context: Context, label: String, @@ -3754,7 +3834,7 @@ fn create_ipc_handler( Box::new(move |request| { #[cfg(windows)] if _kind == WebviewKind::WindowContent - && undecorated_resizing::handle_request(context.clone(), window_id, &request) + && undecorated_resizing::handle_request(context.clone(), *window_id.lock().unwrap(), &request) { return; } @@ -3764,7 +3844,7 @@ fn create_ipc_handler( DetachedWebview { label: label.clone(), dispatcher: WryWebviewDispatcher { - window_id, + window_id: window_id.clone(), webview_id, context: context.clone(), }, diff --git a/core/tauri-runtime/src/lib.rs b/core/tauri-runtime/src/lib.rs index 4996c8aed..d76378b08 100644 --- a/core/tauri-runtime/src/lib.rs +++ b/core/tauri-runtime/src/lib.rs @@ -449,6 +449,9 @@ pub trait WebviewDispatch: Debug + Clone + Send + Sync + Sized + ' /// Executes javascript on the window this [`WindowDispatch`] represents. fn eval_script>(&self, script: S) -> Result<()>; + + /// Moves the webview to the given window. + fn reparent(&self, window_id: WindowId) -> Result<()>; } /// Window dispatcher. A thread-safe handle to the window APIs. diff --git a/core/tauri/build.rs b/core/tauri/build.rs index b0497c2a7..100865947 100644 --- a/core/tauri/build.rs +++ b/core/tauri/build.rs @@ -122,6 +122,7 @@ const PLUGINS: &[(&str, &[(&str, bool)])] = &[ ("set_webview_position", false), ("set_webview_focus", false), ("print", false), + ("reparent", false), // internal ("internal_toggle_devtools", true), ], diff --git a/core/tauri/permissions/webview/autogenerated/reference.md b/core/tauri/permissions/webview/autogenerated/reference.md index c845e562c..0307ac225 100644 --- a/core/tauri/permissions/webview/autogenerated/reference.md +++ b/core/tauri/permissions/webview/autogenerated/reference.md @@ -32,6 +32,14 @@ Enables the print command without any pre-configured scope. Denies the print command without any pre-configured scope. +## allow-reparent + +Enables the reparent command without any pre-configured scope. + +## deny-reparent + +Denies the reparent command without any pre-configured scope. + ## allow-set-webview-focus Enables the set_webview_focus command without any pre-configured scope. diff --git a/core/tauri/scripts/bundle.global.js b/core/tauri/scripts/bundle.global.js index 73acfd4f3..86986601f 100644 --- a/core/tauri/scripts/bundle.global.js +++ b/core/tauri/scripts/bundle.global.js @@ -1 +1 @@ -var __TAURI_IIFE__=function(e){"use strict";function t(e,t,n,i){if("a"===n&&!i)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof t?e!==t||!i:!t.has(e))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===n?i:"a"===n?i.call(e):i?i.value:t.get(e)}function n(e,t,n,i,r){if("m"===i)throw new TypeError("Private method is not writable");if("a"===i&&!r)throw new TypeError("Private accessor was defined without a setter");if("function"==typeof t?e!==t||!r:!t.has(e))throw new TypeError("Cannot write private member to an object whose class did not declare it");return"a"===i?r.call(e,n):r?r.value=n:t.set(e,n),n}var i,r;function a(e,t=!1){return window.__TAURI_INTERNALS__.transformCallback(e,t)}"function"==typeof SuppressedError&&SuppressedError;class s{constructor(){this.__TAURI_CHANNEL_MARKER__=!0,i.set(this,(()=>{})),this.id=a((e=>{t(this,i,"f").call(this,e)}))}set onmessage(e){n(this,i,e,"f")}get onmessage(){return t(this,i,"f")}toJSON(){return`__CHANNEL__:${this.id}`}}i=new WeakMap;class l{constructor(e,t,n){this.plugin=e,this.event=t,this.channelId=n}async unregister(){return o(`plugin:${this.plugin}|remove_listener`,{event:this.event,channelId:this.channelId})}}async function o(e,t={},n){return window.__TAURI_INTERNALS__.invoke(e,t,n)}class u{get rid(){return t(this,r,"f")}constructor(e){r.set(this,void 0),n(this,r,e,"f")}async close(){return o("plugin:resources|close",{rid:this.rid})}}r=new WeakMap;var c=Object.freeze({__proto__:null,Channel:s,PluginListener:l,Resource:u,addPluginListener:async function(e,t,n){const i=new s;return i.onmessage=n,o(`plugin:${e}|register_listener`,{event:t,handler:i}).then((()=>new l(e,t,i.id)))},convertFileSrc:function(e,t="asset"){return window.__TAURI_INTERNALS__.convertFileSrc(e,t)},invoke:o,transformCallback:a});var d,p=Object.freeze({__proto__:null,getName:async function(){return o("plugin:app|name")},getTauriVersion:async function(){return o("plugin:app|tauri_version")},getVersion:async function(){return o("plugin:app|version")},hide:async function(){return o("plugin:app|app_hide")},show:async function(){return o("plugin:app|app_show")}});async function h(e,t){await o("plugin:event|unlisten",{event:e,eventId:t})}async function y(e,t,n){const i="string"==typeof n?.target?{kind:"AnyLabel",label:n.target}:n?.target??{kind:"Any"};return o("plugin:event|listen",{event:e,target:i,handler:a(t)}).then((t=>async()=>h(e,t)))}async function w(e,t,n){return y(e,(n=>{t(n),h(e,n.id).catch((()=>{}))}),n)}async function g(e,t){await o("plugin:event|emit",{event:e,payload:t})}async function b(e,t,n){const i="string"==typeof e?{kind:"AnyLabel",label:e}:e;await o("plugin:event|emit_to",{target:i,event:t,payload:n})}!function(e){e.WINDOW_RESIZED="tauri://resize",e.WINDOW_MOVED="tauri://move",e.WINDOW_CLOSE_REQUESTED="tauri://close-requested",e.WINDOW_DESTROYED="tauri://destroyed",e.WINDOW_FOCUS="tauri://focus",e.WINDOW_BLUR="tauri://blur",e.WINDOW_SCALE_FACTOR_CHANGED="tauri://scale-change",e.WINDOW_THEME_CHANGED="tauri://theme-changed",e.WEBVIEW_CREATED="tauri://webview-created",e.FILE_DROP="tauri://file-drop",e.FILE_DROP_HOVER="tauri://file-drop-hover",e.FILE_DROP_CANCELLED="tauri://file-drop-cancelled"}(d||(d={}));var _=Object.freeze({__proto__:null,get TauriEvent(){return d},emit:g,emitTo:b,listen:y,once:w});class m{constructor(e,t){this.type="Logical",this.width=e,this.height=t}}class f{constructor(e,t){this.type="Physical",this.width=e,this.height=t}toLogical(e){return new m(this.width/e,this.height/e)}}class v{constructor(e,t){this.type="Logical",this.x=e,this.y=t}}class k{constructor(e,t){this.type="Physical",this.x=e,this.y=t}toLogical(e){return new v(this.x/e,this.y/e)}}var A,E,D=Object.freeze({__proto__:null,LogicalPosition:v,LogicalSize:m,PhysicalPosition:k,PhysicalSize:f});!function(e){e[e.Critical=1]="Critical",e[e.Informational=2]="Informational"}(A||(A={}));class L{constructor(e){this._preventDefault=!1,this.event=e.event,this.id=e.id}preventDefault(){this._preventDefault=!0}isPreventDefault(){return this._preventDefault}}function P(){return new T(window.__TAURI_INTERNALS__.metadata.currentWindow.label,{skip:!0})}function I(){return window.__TAURI_INTERNALS__.metadata.windows.map((e=>new T(e.label,{skip:!0})))}!function(e){e.None="none",e.Normal="normal",e.Indeterminate="indeterminate",e.Paused="paused",e.Error="error"}(E||(E={}));const S=["tauri://created","tauri://error"];class T{constructor(e,t={}){this.label=e,this.listeners=Object.create(null),t?.skip||o("plugin:window|create",{options:{...t,parent:"string"==typeof t.parent?t.parent:t.parent?.label,label:e}}).then((async()=>this.emit("tauri://created"))).catch((async e=>this.emit("tauri://error",e)))}static getByLabel(e){return I().find((t=>t.label===e))??null}static getCurrent(){return P()}static getAll(){return I()}static async getFocusedWindow(){for(const e of I())if(await e.isFocused())return e;return null}async listen(e,t){return this._handleTauriEvent(e,t)?Promise.resolve((()=>{const n=this.listeners[e];n.splice(n.indexOf(t),1)})):y(e,t,{target:{kind:"Window",label:this.label}})}async once(e,t){return this._handleTauriEvent(e,t)?Promise.resolve((()=>{const n=this.listeners[e];n.splice(n.indexOf(t),1)})):w(e,t,{target:{kind:"Window",label:this.label}})}async emit(e,t){if(S.includes(e)){for(const n of this.listeners[e]||[])n({event:e,id:-1,payload:t});return Promise.resolve()}return g(e,t)}async emitTo(e,t,n){if(S.includes(t)){for(const e of this.listeners[t]||[])e({event:t,id:-1,payload:n});return Promise.resolve()}return b(e,t,n)}_handleTauriEvent(e,t){return!!S.includes(e)&&(e in this.listeners?this.listeners[e].push(t):this.listeners[e]=[t],!0)}async scaleFactor(){return o("plugin:window|scale_factor",{label:this.label})}async innerPosition(){return o("plugin:window|inner_position",{label:this.label}).then((({x:e,y:t})=>new k(e,t)))}async outerPosition(){return o("plugin:window|outer_position",{label:this.label}).then((({x:e,y:t})=>new k(e,t)))}async innerSize(){return o("plugin:window|inner_size",{label:this.label}).then((({width:e,height:t})=>new f(e,t)))}async outerSize(){return o("plugin:window|outer_size",{label:this.label}).then((({width:e,height:t})=>new f(e,t)))}async isFullscreen(){return o("plugin:window|is_fullscreen",{label:this.label})}async isMinimized(){return o("plugin:window|is_minimized",{label:this.label})}async isMaximized(){return o("plugin:window|is_maximized",{label:this.label})}async isFocused(){return o("plugin:window|is_focused",{label:this.label})}async isDecorated(){return o("plugin:window|is_decorated",{label:this.label})}async isResizable(){return o("plugin:window|is_resizable",{label:this.label})}async isMaximizable(){return o("plugin:window|is_maximizable",{label:this.label})}async isMinimizable(){return o("plugin:window|is_minimizable",{label:this.label})}async isClosable(){return o("plugin:window|is_closable",{label:this.label})}async isVisible(){return o("plugin:window|is_visible",{label:this.label})}async title(){return o("plugin:window|title",{label:this.label})}async theme(){return o("plugin:window|theme",{label:this.label})}async center(){return o("plugin:window|center",{label:this.label})}async requestUserAttention(e){let t=null;return e&&(t=e===A.Critical?{type:"Critical"}:{type:"Informational"}),o("plugin:window|request_user_attention",{label:this.label,value:t})}async setResizable(e){return o("plugin:window|set_resizable",{label:this.label,value:e})}async setMaximizable(e){return o("plugin:window|set_maximizable",{label:this.label,value:e})}async setMinimizable(e){return o("plugin:window|set_minimizable",{label:this.label,value:e})}async setClosable(e){return o("plugin:window|set_closable",{label:this.label,value:e})}async setTitle(e){return o("plugin:window|set_title",{label:this.label,value:e})}async maximize(){return o("plugin:window|maximize",{label:this.label})}async unmaximize(){return o("plugin:window|unmaximize",{label:this.label})}async toggleMaximize(){return o("plugin:window|toggle_maximize",{label:this.label})}async minimize(){return o("plugin:window|minimize",{label:this.label})}async unminimize(){return o("plugin:window|unminimize",{label:this.label})}async show(){return o("plugin:window|show",{label:this.label})}async hide(){return o("plugin:window|hide",{label:this.label})}async close(){return o("plugin:window|close",{label:this.label})}async destroy(){return o("plugin:window|destroy",{label:this.label})}async setDecorations(e){return o("plugin:window|set_decorations",{label:this.label,value:e})}async setShadow(e){return o("plugin:window|set_shadow",{label:this.label,value:e})}async setEffects(e){return o("plugin:window|set_effects",{label:this.label,value:e})}async clearEffects(){return o("plugin:window|set_effects",{label:this.label,value:null})}async setAlwaysOnTop(e){return o("plugin:window|set_always_on_top",{label:this.label,value:e})}async setAlwaysOnBottom(e){return o("plugin:window|set_always_on_bottom",{label:this.label,value:e})}async setContentProtected(e){return o("plugin:window|set_content_protected",{label:this.label,value:e})}async setSize(e){if(!e||"Logical"!==e.type&&"Physical"!==e.type)throw new Error("the `size` argument must be either a LogicalSize or a PhysicalSize instance");return o("plugin:window|set_size",{label:this.label,value:{type:e.type,data:{width:e.width,height:e.height}}})}async setMinSize(e){if(e&&"Logical"!==e.type&&"Physical"!==e.type)throw new Error("the `size` argument must be either a LogicalSize or a PhysicalSize instance");return o("plugin:window|set_min_size",{label:this.label,value:e?{type:e.type,data:{width:e.width,height:e.height}}:null})}async setMaxSize(e){if(e&&"Logical"!==e.type&&"Physical"!==e.type)throw new Error("the `size` argument must be either a LogicalSize or a PhysicalSize instance");return o("plugin:window|set_max_size",{label:this.label,value:e?{type:e.type,data:{width:e.width,height:e.height}}:null})}async setPosition(e){if(!e||"Logical"!==e.type&&"Physical"!==e.type)throw new Error("the `position` argument must be either a LogicalPosition or a PhysicalPosition instance");return o("plugin:window|set_position",{label:this.label,value:{type:e.type,data:{x:e.x,y:e.y}}})}async setFullscreen(e){return o("plugin:window|set_fullscreen",{label:this.label,value:e})}async setFocus(){return o("plugin:window|set_focus",{label:this.label})}async setIcon(e){return o("plugin:window|set_icon",{label:this.label,value:"string"==typeof e?e:Array.from(e)})}async setSkipTaskbar(e){return o("plugin:window|set_skip_taskbar",{label:this.label,value:e})}async setCursorGrab(e){return o("plugin:window|set_cursor_grab",{label:this.label,value:e})}async setCursorVisible(e){return o("plugin:window|set_cursor_visible",{label:this.label,value:e})}async setCursorIcon(e){return o("plugin:window|set_cursor_icon",{label:this.label,value:e})}async setCursorPosition(e){if(!e||"Logical"!==e.type&&"Physical"!==e.type)throw new Error("the `position` argument must be either a LogicalPosition or a PhysicalPosition instance");return o("plugin:window|set_cursor_position",{label:this.label,value:{type:e.type,data:{x:e.x,y:e.y}}})}async setIgnoreCursorEvents(e){return o("plugin:window|set_ignore_cursor_events",{label:this.label,value:e})}async startDragging(){return o("plugin:window|start_dragging",{label:this.label})}async startResizeDragging(e){return o("plugin:window|start_resize_dragging",{label:this.label,value:e})}async setProgressBar(e){return o("plugin:window|set_progress_bar",{label:this.label,value:e})}async setVisibleOnAllWorkspaces(e){return o("plugin:window|set_visible_on_all_workspaces",{label:this.label,value:e})}async onResized(e){return this.listen(d.WINDOW_RESIZED,(t=>{t.payload=F(t.payload),e(t)}))}async onMoved(e){return this.listen(d.WINDOW_MOVED,(t=>{t.payload=z(t.payload),e(t)}))}async onCloseRequested(e){return this.listen(d.WINDOW_CLOSE_REQUESTED,(t=>{const n=new L(t);Promise.resolve(e(n)).then((()=>{if(!n.isPreventDefault())return this.destroy()}))}))}async onFileDropEvent(e){const t=await this.listen(d.FILE_DROP,(t=>{e({...t,payload:{type:"drop",paths:t.payload.paths,position:z(t.payload.position)}})})),n=await this.listen(d.FILE_DROP_HOVER,(t=>{e({...t,payload:{type:"hover",paths:t.payload.paths,position:z(t.payload.position)}})})),i=await this.listen(d.FILE_DROP_CANCELLED,(t=>{e({...t,payload:{type:"cancel"}})}));return()=>{t(),n(),i()}}async onFocusChanged(e){const t=await this.listen(d.WINDOW_FOCUS,(t=>{e({...t,payload:!0})})),n=await this.listen(d.WINDOW_BLUR,(t=>{e({...t,payload:!1})}));return()=>{t(),n()}}async onScaleChanged(e){return this.listen(d.WINDOW_SCALE_FACTOR_CHANGED,e)}async onThemeChanged(e){return this.listen(d.WINDOW_THEME_CHANGED,e)}}var C,x;function R(e){return null===e?null:{name:e.name,scaleFactor:e.scaleFactor,position:z(e.position),size:F(e.size)}}function z(e){return new k(e.x,e.y)}function F(e){return new f(e.width,e.height)}!function(e){e.AppearanceBased="appearanceBased",e.Light="light",e.Dark="dark",e.MediumLight="mediumLight",e.UltraDark="ultraDark",e.Titlebar="titlebar",e.Selection="selection",e.Menu="menu",e.Popover="popover",e.Sidebar="sidebar",e.HeaderView="headerView",e.Sheet="sheet",e.WindowBackground="windowBackground",e.HudWindow="hudWindow",e.FullScreenUI="fullScreenUI",e.Tooltip="tooltip",e.ContentBackground="contentBackground",e.UnderWindowBackground="underWindowBackground",e.UnderPageBackground="underPageBackground",e.Mica="mica",e.Blur="blur",e.Acrylic="acrylic",e.Tabbed="tabbed",e.TabbedDark="tabbedDark",e.TabbedLight="tabbedLight"}(C||(C={})),function(e){e.FollowsWindowActiveState="followsWindowActiveState",e.Active="active",e.Inactive="inactive"}(x||(x={}));var O=Object.freeze({__proto__:null,CloseRequestedEvent:L,get Effect(){return C},get EffectState(){return x},LogicalPosition:v,LogicalSize:m,PhysicalPosition:k,PhysicalSize:f,get ProgressBarStatus(){return E},get UserAttentionType(){return A},Window:T,availableMonitors:async function(){return o("plugin:window|available_monitors").then((e=>e.map(R)))},currentMonitor:async function(){return o("plugin:window|current_monitor").then(R)},getAll:I,getCurrent:P,primaryMonitor:async function(){return o("plugin:window|primary_monitor").then(R)}});function W(){return new U(P(),window.__TAURI_INTERNALS__.metadata.currentWebview.label,{skip:!0})}function N(){return window.__TAURI_INTERNALS__.metadata.webviews.map((e=>new U(T.getByLabel(e.windowLabel),e.label,{skip:!0})))}const M=["tauri://created","tauri://error"];class U{constructor(e,t,n){this.window=e,this.label=t,this.listeners=Object.create(null),n?.skip||o("plugin:webview|create_webview",{windowLabel:e.label,label:t,options:n}).then((async()=>this.emit("tauri://created"))).catch((async e=>this.emit("tauri://error",e)))}static getByLabel(e){return N().find((t=>t.label===e))??null}static getCurrent(){return W()}static getAll(){return N()}async listen(e,t){return this._handleTauriEvent(e,t)?Promise.resolve((()=>{const n=this.listeners[e];n.splice(n.indexOf(t),1)})):y(e,t,{target:{kind:"Webview",label:this.label}})}async once(e,t){return this._handleTauriEvent(e,t)?Promise.resolve((()=>{const n=this.listeners[e];n.splice(n.indexOf(t),1)})):w(e,t,{target:{kind:"Webview",label:this.label}})}async emit(e,t){if(M.includes(e)){for(const n of this.listeners[e]||[])n({event:e,id:-1,payload:t});return Promise.resolve()}return g(e,t)}async emitTo(e,t,n){if(M.includes(t)){for(const e of this.listeners[t]||[])e({event:t,id:-1,payload:n});return Promise.resolve()}return b(e,t,n)}_handleTauriEvent(e,t){return!!M.includes(e)&&(e in this.listeners?this.listeners[e].push(t):this.listeners[e]=[t],!0)}async position(){return o("plugin:webview|webview_position",{label:this.label}).then((({x:e,y:t})=>new k(e,t)))}async size(){return o("plugin:webview|webview_size",{label:this.label}).then((({width:e,height:t})=>new f(e,t)))}async close(){return o("plugin:webview|close",{label:this.label})}async setSize(e){if(!e||"Logical"!==e.type&&"Physical"!==e.type)throw new Error("the `size` argument must be either a LogicalSize or a PhysicalSize instance");return o("plugin:webview|set_webview_size",{label:this.label,value:{type:e.type,data:{width:e.width,height:e.height}}})}async setPosition(e){if(!e||"Logical"!==e.type&&"Physical"!==e.type)throw new Error("the `position` argument must be either a LogicalPosition or a PhysicalPosition instance");return o("plugin:webview|set_webview_position",{label:this.label,value:{type:e.type,data:{x:e.x,y:e.y}}})}async setFocus(){return o("plugin:webview|set_webview_focus",{label:this.label})}async onFileDropEvent(e){const t=await this.listen(d.FILE_DROP,(t=>{e({...t,payload:{type:"drop",paths:t.payload.paths,position:B(t.payload.position)}})})),n=await this.listen(d.FILE_DROP_HOVER,(t=>{e({...t,payload:{type:"hover",paths:t.payload.paths,position:B(t.payload.position)}})})),i=await this.listen(d.FILE_DROP_CANCELLED,(t=>{e({...t,payload:{type:"cancel"}})}));return()=>{t(),n(),i()}}}function B(e){return new k(e.x,e.y)}var V,j,H=Object.freeze({__proto__:null,Webview:U,getAll:N,getCurrent:W});function G(){const e=W();return new Q(e.label,{skip:!0})}function q(){return window.__TAURI_INTERNALS__.metadata.webviews.map((e=>new Q(e.label,{skip:!0})))}class Q{constructor(e,t={}){this.label=e,this.listeners=Object.create(null),t?.skip||o("plugin:webview|create_webview_window",{options:{...t,parent:"string"==typeof t.parent?t.parent:t.parent?.label,label:e}}).then((async()=>this.emit("tauri://created"))).catch((async e=>this.emit("tauri://error",e)))}static getByLabel(e){const t=q().find((t=>t.label===e))??null;return t?new Q(t.label,{skip:!0}):null}static getCurrent(){return G()}static getAll(){return q().map((e=>new Q(e.label,{skip:!0})))}async listen(e,t){return this._handleTauriEvent(e,t)?Promise.resolve((()=>{const n=this.listeners[e];n.splice(n.indexOf(t),1)})):y(e,t,{target:{kind:"WebviewWindow",label:this.label}})}async once(e,t){return this._handleTauriEvent(e,t)?Promise.resolve((()=>{const n=this.listeners[e];n.splice(n.indexOf(t),1)})):w(e,t,{target:{kind:"WebviewWindow",label:this.label}})}}V=Q,j=[T,U],(Array.isArray(j)?j:[j]).forEach((e=>{Object.getOwnPropertyNames(e.prototype).forEach((t=>{"object"==typeof V.prototype&&V.prototype&&t in V.prototype||Object.defineProperty(V.prototype,t,Object.getOwnPropertyDescriptor(e.prototype,t)??Object.create(null))}))}));var $,Z=Object.freeze({__proto__:null,WebviewWindow:Q,getAll:q,getCurrent:G});!function(e){e[e.Audio=1]="Audio",e[e.Cache=2]="Cache",e[e.Config=3]="Config",e[e.Data=4]="Data",e[e.LocalData=5]="LocalData",e[e.Document=6]="Document",e[e.Download=7]="Download",e[e.Picture=8]="Picture",e[e.Public=9]="Public",e[e.Video=10]="Video",e[e.Resource=11]="Resource",e[e.Temp=12]="Temp",e[e.AppConfig=13]="AppConfig",e[e.AppData=14]="AppData",e[e.AppLocalData=15]="AppLocalData",e[e.AppCache=16]="AppCache",e[e.AppLog=17]="AppLog",e[e.Desktop=18]="Desktop",e[e.Executable=19]="Executable",e[e.Font=20]="Font",e[e.Home=21]="Home",e[e.Runtime=22]="Runtime",e[e.Template=23]="Template"}($||($={}));var J=Object.freeze({__proto__:null,get BaseDirectory(){return $},appCacheDir:async function(){return o("plugin:path|resolve_directory",{directory:$.AppCache})},appConfigDir:async function(){return o("plugin:path|resolve_directory",{directory:$.AppConfig})},appDataDir:async function(){return o("plugin:path|resolve_directory",{directory:$.AppData})},appLocalDataDir:async function(){return o("plugin:path|resolve_directory",{directory:$.AppLocalData})},appLogDir:async function(){return o("plugin:path|resolve_directory",{directory:$.AppLog})},audioDir:async function(){return o("plugin:path|resolve_directory",{directory:$.Audio})},basename:async function(e,t){return o("plugin:path|basename",{path:e,ext:t})},cacheDir:async function(){return o("plugin:path|resolve_directory",{directory:$.Cache})},configDir:async function(){return o("plugin:path|resolve_directory",{directory:$.Config})},dataDir:async function(){return o("plugin:path|resolve_directory",{directory:$.Data})},delimiter:function(){return window.__TAURI_INTERNALS__.plugins.path.delimiter},desktopDir:async function(){return o("plugin:path|resolve_directory",{directory:$.Desktop})},dirname:async function(e){return o("plugin:path|dirname",{path:e})},documentDir:async function(){return o("plugin:path|resolve_directory",{directory:$.Document})},downloadDir:async function(){return o("plugin:path|resolve_directory",{directory:$.Download})},executableDir:async function(){return o("plugin:path|resolve_directory",{directory:$.Executable})},extname:async function(e){return o("plugin:path|extname",{path:e})},fontDir:async function(){return o("plugin:path|resolve_directory",{directory:$.Font})},homeDir:async function(){return o("plugin:path|resolve_directory",{directory:$.Home})},isAbsolute:async function(e){return o("plugin:path|isAbsolute",{path:e})},join:async function(...e){return o("plugin:path|join",{paths:e})},localDataDir:async function(){return o("plugin:path|resolve_directory",{directory:$.LocalData})},normalize:async function(e){return o("plugin:path|normalize",{path:e})},pictureDir:async function(){return o("plugin:path|resolve_directory",{directory:$.Picture})},publicDir:async function(){return o("plugin:path|resolve_directory",{directory:$.Public})},resolve:async function(...e){return o("plugin:path|resolve",{paths:e})},resolveResource:async function(e){return o("plugin:path|resolve_directory",{directory:$.Resource,path:e})},resourceDir:async function(){return o("plugin:path|resolve_directory",{directory:$.Resource})},runtimeDir:async function(){return o("plugin:path|resolve_directory",{directory:$.Runtime})},sep:function(){return window.__TAURI_INTERNALS__.plugins.path.sep},tempDir:async function(){return o("plugin:path|resolve_directory",{directory:$.Temp})},templateDir:async function(){return o("plugin:path|resolve_directory",{directory:$.Template})},videoDir:async function(){return o("plugin:path|resolve_directory",{directory:$.Video})}});class K extends u{constructor(e,t){super(e),this.id=t}static async new(e){e?.menu&&(e.menu=[e.menu.rid,e.menu.kind]),e?.icon&&(e.icon="string"==typeof e.icon?e.icon:Array.from(e.icon));const t=new s;return e?.action&&(t.onmessage=e.action,delete e.action),o("plugin:tray|new",{options:e??{},handler:t}).then((([e,t])=>new K(e,t)))}async setIcon(e){let t=null;return e&&(t="string"==typeof e?e:Array.from(e)),o("plugin:tray|set_icon",{rid:this.rid,icon:t})}async setMenu(e){return e&&(e=[e.rid,e.kind]),o("plugin:tray|set_menu",{rid:this.rid,menu:e})}async setTooltip(e){return o("plugin:tray|set_tooltip",{rid:this.rid,tooltip:e})}async setTitle(e){return o("plugin:tray|set_title",{rid:this.rid,title:e})}async setVisible(e){return o("plugin:tray|set_visible",{rid:this.rid,visible:e})}async setTempDirPath(e){return o("plugin:tray|set_temp_dir_path",{rid:this.rid,path:e})}async setIconAsTemplate(e){return o("plugin:tray|set_icon_as_template",{rid:this.rid,asTemplate:e})}async setMenuOnLeftClick(e){return o("plugin:tray|set_show_menu_on_left_click",{rid:this.rid,onLeft:e})}}var Y,X,ee,te=Object.freeze({__proto__:null,TrayIcon:K});function ne(e){if("items"in e)e.items=e.items?.map((e=>"rid"in e?e:ne(e)));else if("action"in e&&e.action){const t=new s;return t.onmessage=e.action,delete e.action,{...e,handler:t}}return e}async function ie(e,t){const n=new s;let i=null;return t&&"object"==typeof t&&("action"in t&&t.action&&(n.onmessage=t.action,delete t.action),"items"in t&&t.items&&(i=t.items.map((e=>"rid"in e?[e.rid,e.kind]:ne(e))))),o("plugin:menu|new",{kind:e,options:t?{...t,items:i}:void 0,handler:n})}class re extends u{get id(){return t(this,Y,"f")}get kind(){return t(this,X,"f")}constructor(e,t,i){super(e),Y.set(this,void 0),X.set(this,void 0),n(this,Y,t,"f"),n(this,X,i,"f")}}Y=new WeakMap,X=new WeakMap;class ae extends re{constructor(e,t){super(e,t,"MenuItem")}static async new(e){return ie("MenuItem",e).then((([e,t])=>new ae(e,t)))}async text(){return o("plugin:menu|text",{rid:this.rid,kind:this.kind})}async setText(e){return o("plugin:menu|set_text",{rid:this.rid,kind:this.kind,text:e})}async isEnabled(){return o("plugin:menu|is_enabled",{rid:this.rid,kind:this.kind})}async setEnabled(e){return o("plugin:menu|set_enabled",{rid:this.rid,kind:this.kind,enabled:e})}async setAccelerator(e){return o("plugin:menu|set_accelerator",{rid:this.rid,kind:this.kind,accelerator:e})}}class se extends re{constructor(e,t){super(e,t,"Check")}static async new(e){return ie("Check",e).then((([e,t])=>new se(e,t)))}async text(){return o("plugin:menu|text",{rid:this.rid,kind:this.kind})}async setText(e){return o("plugin:menu|set_text",{rid:this.rid,kind:this.kind,text:e})}async isEnabled(){return o("plugin:menu|is_enabled",{rid:this.rid,kind:this.kind})}async setEnabled(e){return o("plugin:menu|set_enabled",{rid:this.rid,kind:this.kind,enabled:e})}async setAccelerator(e){return o("plugin:menu|set_accelerator",{rid:this.rid,kind:this.kind,accelerator:e})}async isChecked(){return o("plugin:menu|is_checked",{rid:this.rid})}async setChecked(e){return o("plugin:menu|set_checked",{rid:this.rid,checked:e})}}!function(e){e.Add="Add",e.Advanced="Advanced",e.Bluetooth="Bluetooth",e.Bookmarks="Bookmarks",e.Caution="Caution",e.ColorPanel="ColorPanel",e.ColumnView="ColumnView",e.Computer="Computer",e.EnterFullScreen="EnterFullScreen",e.Everyone="Everyone",e.ExitFullScreen="ExitFullScreen",e.FlowView="FlowView",e.Folder="Folder",e.FolderBurnable="FolderBurnable",e.FolderSmart="FolderSmart",e.FollowLinkFreestanding="FollowLinkFreestanding",e.FontPanel="FontPanel",e.GoLeft="GoLeft",e.GoRight="GoRight",e.Home="Home",e.IChatTheater="IChatTheater",e.IconView="IconView",e.Info="Info",e.InvalidDataFreestanding="InvalidDataFreestanding",e.LeftFacingTriangle="LeftFacingTriangle",e.ListView="ListView",e.LockLocked="LockLocked",e.LockUnlocked="LockUnlocked",e.MenuMixedState="MenuMixedState",e.MenuOnState="MenuOnState",e.MobileMe="MobileMe",e.MultipleDocuments="MultipleDocuments",e.Network="Network",e.Path="Path",e.PreferencesGeneral="PreferencesGeneral",e.QuickLook="QuickLook",e.RefreshFreestanding="RefreshFreestanding",e.Refresh="Refresh",e.Remove="Remove",e.RevealFreestanding="RevealFreestanding",e.RightFacingTriangle="RightFacingTriangle",e.Share="Share",e.Slideshow="Slideshow",e.SmartBadge="SmartBadge",e.StatusAvailable="StatusAvailable",e.StatusNone="StatusNone",e.StatusPartiallyAvailable="StatusPartiallyAvailable",e.StatusUnavailable="StatusUnavailable",e.StopProgressFreestanding="StopProgressFreestanding",e.StopProgress="StopProgress",e.TrashEmpty="TrashEmpty",e.TrashFull="TrashFull",e.User="User",e.UserAccounts="UserAccounts",e.UserGroup="UserGroup",e.UserGuest="UserGuest"}(ee||(ee={}));class le extends re{constructor(e,t){super(e,t,"Icon")}static async new(e){return ie("Icon",e).then((([e,t])=>new le(e,t)))}async text(){return o("plugin:menu|text",{rid:this.rid,kind:this.kind})}async setText(e){return o("plugin:menu|set_text",{rid:this.rid,kind:this.kind,text:e})}async isEnabled(){return o("plugin:menu|is_enabled",{rid:this.rid,kind:this.kind})}async setEnabled(e){return o("plugin:menu|set_enabled",{rid:this.rid,kind:this.kind,enabled:e})}async setAccelerator(e){return o("plugin:menu|set_accelerator",{rid:this.rid,kind:this.kind,accelerator:e})}async setIcon(e){return o("plugin:menu|set_icon",{rid:this.rid,icon:e})}}class oe extends re{constructor(e,t){super(e,t,"Predefined")}static async new(e){return ie("Predefined",e).then((([e,t])=>new oe(e,t)))}async text(){return o("plugin:menu|text",{rid:this.rid,kind:this.kind})}async setText(e){return o("plugin:menu|set_text",{rid:this.rid,kind:this.kind,text:e})}}function ue([e,t,n]){switch(n){case"Submenu":return new ce(e,t);case"Predefined":return new oe(e,t);case"Check":return new se(e,t);case"Icon":return new le(e,t);default:return new ae(e,t)}}class ce extends re{constructor(e,t){super(e,t,"Submenu")}static async new(e){return ie("Submenu",e).then((([e,t])=>new ce(e,t)))}async text(){return o("plugin:menu|text",{rid:this.rid,kind:this.kind})}async setText(e){return o("plugin:menu|set_text",{rid:this.rid,kind:this.kind,text:e})}async isEnabled(){return o("plugin:menu|is_enabled",{rid:this.rid,kind:this.kind})}async setEnabled(e){return o("plugin:menu|set_enabled",{rid:this.rid,kind:this.kind,enabled:e})}async append(e){return o("plugin:menu|append",{rid:this.rid,kind:this.kind,items:(Array.isArray(e)?e:[e]).map((e=>"rid"in e?[e.rid,e.kind]:e))})}async prepend(e){return o("plugin:menu|prepend",{rid:this.rid,kind:this.kind,items:(Array.isArray(e)?e:[e]).map((e=>"rid"in e?[e.rid,e.kind]:e))})}async insert(e,t){return o("plugin:menu|insert",{rid:this.rid,kind:this.kind,items:(Array.isArray(e)?e:[e]).map((e=>"rid"in e?[e.rid,e.kind]:e)),position:t})}async remove(e){return o("plugin:menu|remove",{rid:this.rid,kind:this.kind,item:[e.rid,e.kind]})}async removeAt(e){return o("plugin:menu|remove_at",{rid:this.rid,kind:this.kind,position:e}).then(ue)}async items(){return o("plugin:menu|items",{rid:this.rid,kind:this.kind}).then((e=>e.map(ue)))}async get(e){return o("plugin:menu|get",{rid:this.rid,kind:this.kind,id:e}).then((e=>e?ue(e):null))}async popup(e,t){let n=null;return e&&(n={type:e instanceof k?"Physical":"Logical",data:e}),o("plugin:menu|popup",{rid:this.rid,kind:this.kind,window:t?.label??null,at:n})}async setAsWindowsMenuForNSApp(){return o("plugin:menu|set_as_windows_menu_for_nsapp",{rid:this.rid})}async setAsHelpMenuForNSApp(){return o("plugin:menu|set_as_help_menu_for_nsapp",{rid:this.rid})}}function de([e,t,n]){switch(n){case"Submenu":return new ce(e,t);case"Predefined":return new oe(e,t);case"Check":return new se(e,t);case"Icon":return new le(e,t);default:return new ae(e,t)}}class pe extends re{constructor(e,t){super(e,t,"Menu")}static async new(e){return ie("Menu",e).then((([e,t])=>new pe(e,t)))}static async default(){return o("plugin:menu|create_default").then((([e,t])=>new pe(e,t)))}async append(e){return o("plugin:menu|append",{rid:this.rid,kind:this.kind,items:(Array.isArray(e)?e:[e]).map((e=>"rid"in e?[e.rid,e.kind]:e))})}async prepend(e){return o("plugin:menu|prepend",{rid:this.rid,kind:this.kind,items:(Array.isArray(e)?e:[e]).map((e=>"rid"in e?[e.rid,e.kind]:e))})}async insert(e,t){return o("plugin:menu|insert",{rid:this.rid,kind:this.kind,items:(Array.isArray(e)?e:[e]).map((e=>"rid"in e?[e.rid,e.kind]:e)),position:t})}async remove(e){return o("plugin:menu|remove",{rid:this.rid,kind:this.kind,item:[e.rid,e.kind]})}async removeAt(e){return o("plugin:menu|remove_at",{rid:this.rid,kind:this.kind,position:e}).then(de)}async items(){return o("plugin:menu|items",{rid:this.rid,kind:this.kind}).then((e=>e.map(de)))}async get(e){return o("plugin:menu|get",{rid:this.rid,kind:this.kind,id:e}).then((e=>e?de(e):null))}async popup(e,t){let n=null;return e&&(n={type:e instanceof k?"Physical":"Logical",data:e}),o("plugin:menu|popup",{rid:this.rid,kind:this.kind,window:t?.label??null,at:n})}async setAsAppMenu(){return o("plugin:menu|set_as_app_menu",{rid:this.rid}).then((e=>e?new pe(e[0],e[1]):null))}async setAsWindowMenu(e){return o("plugin:menu|set_as_window_menu",{rid:this.rid,window:e?.label??null}).then((e=>e?new pe(e[0],e[1]):null))}}var he=Object.freeze({__proto__:null,CheckMenuItem:se,IconMenuItem:le,Menu:pe,MenuItem:ae,get NativeIcon(){return ee},PredefinedMenuItem:oe,Submenu:ce});return e.app=p,e.core=c,e.dpi=D,e.event=_,e.menu=he,e.path=J,e.tray=te,e.webview=H,e.webviewWindow=Z,e.window=O,e}({});window.__TAURI__=__TAURI_IIFE__; +var __TAURI_IIFE__=function(e){"use strict";function t(e,t,n,i){if("a"===n&&!i)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof t?e!==t||!i:!t.has(e))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===n?i:"a"===n?i.call(e):i?i.value:t.get(e)}function n(e,t,n,i,r){if("m"===i)throw new TypeError("Private method is not writable");if("a"===i&&!r)throw new TypeError("Private accessor was defined without a setter");if("function"==typeof t?e!==t||!r:!t.has(e))throw new TypeError("Cannot write private member to an object whose class did not declare it");return"a"===i?r.call(e,n):r?r.value=n:t.set(e,n),n}var i,r;function a(e,t=!1){return window.__TAURI_INTERNALS__.transformCallback(e,t)}"function"==typeof SuppressedError&&SuppressedError;class s{constructor(){this.__TAURI_CHANNEL_MARKER__=!0,i.set(this,(()=>{})),this.id=a((e=>{t(this,i,"f").call(this,e)}))}set onmessage(e){n(this,i,e,"f")}get onmessage(){return t(this,i,"f")}toJSON(){return`__CHANNEL__:${this.id}`}}i=new WeakMap;class l{constructor(e,t,n){this.plugin=e,this.event=t,this.channelId=n}async unregister(){return o(`plugin:${this.plugin}|remove_listener`,{event:this.event,channelId:this.channelId})}}async function o(e,t={},n){return window.__TAURI_INTERNALS__.invoke(e,t,n)}class u{get rid(){return t(this,r,"f")}constructor(e){r.set(this,void 0),n(this,r,e,"f")}async close(){return o("plugin:resources|close",{rid:this.rid})}}r=new WeakMap;var c=Object.freeze({__proto__:null,Channel:s,PluginListener:l,Resource:u,addPluginListener:async function(e,t,n){const i=new s;return i.onmessage=n,o(`plugin:${e}|register_listener`,{event:t,handler:i}).then((()=>new l(e,t,i.id)))},convertFileSrc:function(e,t="asset"){return window.__TAURI_INTERNALS__.convertFileSrc(e,t)},invoke:o,transformCallback:a});var d,p=Object.freeze({__proto__:null,getName:async function(){return o("plugin:app|name")},getTauriVersion:async function(){return o("plugin:app|tauri_version")},getVersion:async function(){return o("plugin:app|version")},hide:async function(){return o("plugin:app|app_hide")},show:async function(){return o("plugin:app|app_show")}});async function h(e,t){await o("plugin:event|unlisten",{event:e,eventId:t})}async function y(e,t,n){const i="string"==typeof n?.target?{kind:"AnyLabel",label:n.target}:n?.target??{kind:"Any"};return o("plugin:event|listen",{event:e,target:i,handler:a(t)}).then((t=>async()=>h(e,t)))}async function w(e,t,n){return y(e,(n=>{t(n),h(e,n.id).catch((()=>{}))}),n)}async function g(e,t){await o("plugin:event|emit",{event:e,payload:t})}async function b(e,t,n){const i="string"==typeof e?{kind:"AnyLabel",label:e}:e;await o("plugin:event|emit_to",{target:i,event:t,payload:n})}!function(e){e.WINDOW_RESIZED="tauri://resize",e.WINDOW_MOVED="tauri://move",e.WINDOW_CLOSE_REQUESTED="tauri://close-requested",e.WINDOW_DESTROYED="tauri://destroyed",e.WINDOW_FOCUS="tauri://focus",e.WINDOW_BLUR="tauri://blur",e.WINDOW_SCALE_FACTOR_CHANGED="tauri://scale-change",e.WINDOW_THEME_CHANGED="tauri://theme-changed",e.WEBVIEW_CREATED="tauri://webview-created",e.FILE_DROP="tauri://file-drop",e.FILE_DROP_HOVER="tauri://file-drop-hover",e.FILE_DROP_CANCELLED="tauri://file-drop-cancelled"}(d||(d={}));var _=Object.freeze({__proto__:null,get TauriEvent(){return d},emit:g,emitTo:b,listen:y,once:w});class m{constructor(e,t){this.type="Logical",this.width=e,this.height=t}}class f{constructor(e,t){this.type="Physical",this.width=e,this.height=t}toLogical(e){return new m(this.width/e,this.height/e)}}class v{constructor(e,t){this.type="Logical",this.x=e,this.y=t}}class k{constructor(e,t){this.type="Physical",this.x=e,this.y=t}toLogical(e){return new v(this.x/e,this.y/e)}}var A,E,D=Object.freeze({__proto__:null,LogicalPosition:v,LogicalSize:m,PhysicalPosition:k,PhysicalSize:f});!function(e){e[e.Critical=1]="Critical",e[e.Informational=2]="Informational"}(A||(A={}));class L{constructor(e){this._preventDefault=!1,this.event=e.event,this.id=e.id}preventDefault(){this._preventDefault=!0}isPreventDefault(){return this._preventDefault}}function P(){return new T(window.__TAURI_INTERNALS__.metadata.currentWindow.label,{skip:!0})}function I(){return window.__TAURI_INTERNALS__.metadata.windows.map((e=>new T(e.label,{skip:!0})))}!function(e){e.None="none",e.Normal="normal",e.Indeterminate="indeterminate",e.Paused="paused",e.Error="error"}(E||(E={}));const S=["tauri://created","tauri://error"];class T{constructor(e,t={}){this.label=e,this.listeners=Object.create(null),t?.skip||o("plugin:window|create",{options:{...t,parent:"string"==typeof t.parent?t.parent:t.parent?.label,label:e}}).then((async()=>this.emit("tauri://created"))).catch((async e=>this.emit("tauri://error",e)))}static getByLabel(e){return I().find((t=>t.label===e))??null}static getCurrent(){return P()}static getAll(){return I()}static async getFocusedWindow(){for(const e of I())if(await e.isFocused())return e;return null}async listen(e,t){return this._handleTauriEvent(e,t)?Promise.resolve((()=>{const n=this.listeners[e];n.splice(n.indexOf(t),1)})):y(e,t,{target:{kind:"Window",label:this.label}})}async once(e,t){return this._handleTauriEvent(e,t)?Promise.resolve((()=>{const n=this.listeners[e];n.splice(n.indexOf(t),1)})):w(e,t,{target:{kind:"Window",label:this.label}})}async emit(e,t){if(S.includes(e)){for(const n of this.listeners[e]||[])n({event:e,id:-1,payload:t});return Promise.resolve()}return g(e,t)}async emitTo(e,t,n){if(S.includes(t)){for(const e of this.listeners[t]||[])e({event:t,id:-1,payload:n});return Promise.resolve()}return b(e,t,n)}_handleTauriEvent(e,t){return!!S.includes(e)&&(e in this.listeners?this.listeners[e].push(t):this.listeners[e]=[t],!0)}async scaleFactor(){return o("plugin:window|scale_factor",{label:this.label})}async innerPosition(){return o("plugin:window|inner_position",{label:this.label}).then((({x:e,y:t})=>new k(e,t)))}async outerPosition(){return o("plugin:window|outer_position",{label:this.label}).then((({x:e,y:t})=>new k(e,t)))}async innerSize(){return o("plugin:window|inner_size",{label:this.label}).then((({width:e,height:t})=>new f(e,t)))}async outerSize(){return o("plugin:window|outer_size",{label:this.label}).then((({width:e,height:t})=>new f(e,t)))}async isFullscreen(){return o("plugin:window|is_fullscreen",{label:this.label})}async isMinimized(){return o("plugin:window|is_minimized",{label:this.label})}async isMaximized(){return o("plugin:window|is_maximized",{label:this.label})}async isFocused(){return o("plugin:window|is_focused",{label:this.label})}async isDecorated(){return o("plugin:window|is_decorated",{label:this.label})}async isResizable(){return o("plugin:window|is_resizable",{label:this.label})}async isMaximizable(){return o("plugin:window|is_maximizable",{label:this.label})}async isMinimizable(){return o("plugin:window|is_minimizable",{label:this.label})}async isClosable(){return o("plugin:window|is_closable",{label:this.label})}async isVisible(){return o("plugin:window|is_visible",{label:this.label})}async title(){return o("plugin:window|title",{label:this.label})}async theme(){return o("plugin:window|theme",{label:this.label})}async center(){return o("plugin:window|center",{label:this.label})}async requestUserAttention(e){let t=null;return e&&(t=e===A.Critical?{type:"Critical"}:{type:"Informational"}),o("plugin:window|request_user_attention",{label:this.label,value:t})}async setResizable(e){return o("plugin:window|set_resizable",{label:this.label,value:e})}async setMaximizable(e){return o("plugin:window|set_maximizable",{label:this.label,value:e})}async setMinimizable(e){return o("plugin:window|set_minimizable",{label:this.label,value:e})}async setClosable(e){return o("plugin:window|set_closable",{label:this.label,value:e})}async setTitle(e){return o("plugin:window|set_title",{label:this.label,value:e})}async maximize(){return o("plugin:window|maximize",{label:this.label})}async unmaximize(){return o("plugin:window|unmaximize",{label:this.label})}async toggleMaximize(){return o("plugin:window|toggle_maximize",{label:this.label})}async minimize(){return o("plugin:window|minimize",{label:this.label})}async unminimize(){return o("plugin:window|unminimize",{label:this.label})}async show(){return o("plugin:window|show",{label:this.label})}async hide(){return o("plugin:window|hide",{label:this.label})}async close(){return o("plugin:window|close",{label:this.label})}async destroy(){return o("plugin:window|destroy",{label:this.label})}async setDecorations(e){return o("plugin:window|set_decorations",{label:this.label,value:e})}async setShadow(e){return o("plugin:window|set_shadow",{label:this.label,value:e})}async setEffects(e){return o("plugin:window|set_effects",{label:this.label,value:e})}async clearEffects(){return o("plugin:window|set_effects",{label:this.label,value:null})}async setAlwaysOnTop(e){return o("plugin:window|set_always_on_top",{label:this.label,value:e})}async setAlwaysOnBottom(e){return o("plugin:window|set_always_on_bottom",{label:this.label,value:e})}async setContentProtected(e){return o("plugin:window|set_content_protected",{label:this.label,value:e})}async setSize(e){if(!e||"Logical"!==e.type&&"Physical"!==e.type)throw new Error("the `size` argument must be either a LogicalSize or a PhysicalSize instance");return o("plugin:window|set_size",{label:this.label,value:{type:e.type,data:{width:e.width,height:e.height}}})}async setMinSize(e){if(e&&"Logical"!==e.type&&"Physical"!==e.type)throw new Error("the `size` argument must be either a LogicalSize or a PhysicalSize instance");return o("plugin:window|set_min_size",{label:this.label,value:e?{type:e.type,data:{width:e.width,height:e.height}}:null})}async setMaxSize(e){if(e&&"Logical"!==e.type&&"Physical"!==e.type)throw new Error("the `size` argument must be either a LogicalSize or a PhysicalSize instance");return o("plugin:window|set_max_size",{label:this.label,value:e?{type:e.type,data:{width:e.width,height:e.height}}:null})}async setPosition(e){if(!e||"Logical"!==e.type&&"Physical"!==e.type)throw new Error("the `position` argument must be either a LogicalPosition or a PhysicalPosition instance");return o("plugin:window|set_position",{label:this.label,value:{type:e.type,data:{x:e.x,y:e.y}}})}async setFullscreen(e){return o("plugin:window|set_fullscreen",{label:this.label,value:e})}async setFocus(){return o("plugin:window|set_focus",{label:this.label})}async setIcon(e){return o("plugin:window|set_icon",{label:this.label,value:"string"==typeof e?e:Array.from(e)})}async setSkipTaskbar(e){return o("plugin:window|set_skip_taskbar",{label:this.label,value:e})}async setCursorGrab(e){return o("plugin:window|set_cursor_grab",{label:this.label,value:e})}async setCursorVisible(e){return o("plugin:window|set_cursor_visible",{label:this.label,value:e})}async setCursorIcon(e){return o("plugin:window|set_cursor_icon",{label:this.label,value:e})}async setCursorPosition(e){if(!e||"Logical"!==e.type&&"Physical"!==e.type)throw new Error("the `position` argument must be either a LogicalPosition or a PhysicalPosition instance");return o("plugin:window|set_cursor_position",{label:this.label,value:{type:e.type,data:{x:e.x,y:e.y}}})}async setIgnoreCursorEvents(e){return o("plugin:window|set_ignore_cursor_events",{label:this.label,value:e})}async startDragging(){return o("plugin:window|start_dragging",{label:this.label})}async startResizeDragging(e){return o("plugin:window|start_resize_dragging",{label:this.label,value:e})}async setProgressBar(e){return o("plugin:window|set_progress_bar",{label:this.label,value:e})}async setVisibleOnAllWorkspaces(e){return o("plugin:window|set_visible_on_all_workspaces",{label:this.label,value:e})}async onResized(e){return this.listen(d.WINDOW_RESIZED,(t=>{t.payload=F(t.payload),e(t)}))}async onMoved(e){return this.listen(d.WINDOW_MOVED,(t=>{t.payload=z(t.payload),e(t)}))}async onCloseRequested(e){return this.listen(d.WINDOW_CLOSE_REQUESTED,(t=>{const n=new L(t);Promise.resolve(e(n)).then((()=>{if(!n.isPreventDefault())return this.destroy()}))}))}async onFileDropEvent(e){const t=await this.listen(d.FILE_DROP,(t=>{e({...t,payload:{type:"drop",paths:t.payload.paths,position:z(t.payload.position)}})})),n=await this.listen(d.FILE_DROP_HOVER,(t=>{e({...t,payload:{type:"hover",paths:t.payload.paths,position:z(t.payload.position)}})})),i=await this.listen(d.FILE_DROP_CANCELLED,(t=>{e({...t,payload:{type:"cancel"}})}));return()=>{t(),n(),i()}}async onFocusChanged(e){const t=await this.listen(d.WINDOW_FOCUS,(t=>{e({...t,payload:!0})})),n=await this.listen(d.WINDOW_BLUR,(t=>{e({...t,payload:!1})}));return()=>{t(),n()}}async onScaleChanged(e){return this.listen(d.WINDOW_SCALE_FACTOR_CHANGED,e)}async onThemeChanged(e){return this.listen(d.WINDOW_THEME_CHANGED,e)}}var C,x;function R(e){return null===e?null:{name:e.name,scaleFactor:e.scaleFactor,position:z(e.position),size:F(e.size)}}function z(e){return new k(e.x,e.y)}function F(e){return new f(e.width,e.height)}!function(e){e.AppearanceBased="appearanceBased",e.Light="light",e.Dark="dark",e.MediumLight="mediumLight",e.UltraDark="ultraDark",e.Titlebar="titlebar",e.Selection="selection",e.Menu="menu",e.Popover="popover",e.Sidebar="sidebar",e.HeaderView="headerView",e.Sheet="sheet",e.WindowBackground="windowBackground",e.HudWindow="hudWindow",e.FullScreenUI="fullScreenUI",e.Tooltip="tooltip",e.ContentBackground="contentBackground",e.UnderWindowBackground="underWindowBackground",e.UnderPageBackground="underPageBackground",e.Mica="mica",e.Blur="blur",e.Acrylic="acrylic",e.Tabbed="tabbed",e.TabbedDark="tabbedDark",e.TabbedLight="tabbedLight"}(C||(C={})),function(e){e.FollowsWindowActiveState="followsWindowActiveState",e.Active="active",e.Inactive="inactive"}(x||(x={}));var O=Object.freeze({__proto__:null,CloseRequestedEvent:L,get Effect(){return C},get EffectState(){return x},LogicalPosition:v,LogicalSize:m,PhysicalPosition:k,PhysicalSize:f,get ProgressBarStatus(){return E},get UserAttentionType(){return A},Window:T,availableMonitors:async function(){return o("plugin:window|available_monitors").then((e=>e.map(R)))},currentMonitor:async function(){return o("plugin:window|current_monitor").then(R)},getAll:I,getCurrent:P,primaryMonitor:async function(){return o("plugin:window|primary_monitor").then(R)}});function W(){return new U(P(),window.__TAURI_INTERNALS__.metadata.currentWebview.label,{skip:!0})}function N(){return window.__TAURI_INTERNALS__.metadata.webviews.map((e=>new U(T.getByLabel(e.windowLabel),e.label,{skip:!0})))}const M=["tauri://created","tauri://error"];class U{constructor(e,t,n){this.window=e,this.label=t,this.listeners=Object.create(null),n?.skip||o("plugin:webview|create_webview",{windowLabel:e.label,label:t,options:n}).then((async()=>this.emit("tauri://created"))).catch((async e=>this.emit("tauri://error",e)))}static getByLabel(e){return N().find((t=>t.label===e))??null}static getCurrent(){return W()}static getAll(){return N()}async listen(e,t){return this._handleTauriEvent(e,t)?Promise.resolve((()=>{const n=this.listeners[e];n.splice(n.indexOf(t),1)})):y(e,t,{target:{kind:"Webview",label:this.label}})}async once(e,t){return this._handleTauriEvent(e,t)?Promise.resolve((()=>{const n=this.listeners[e];n.splice(n.indexOf(t),1)})):w(e,t,{target:{kind:"Webview",label:this.label}})}async emit(e,t){if(M.includes(e)){for(const n of this.listeners[e]||[])n({event:e,id:-1,payload:t});return Promise.resolve()}return g(e,t)}async emitTo(e,t,n){if(M.includes(t)){for(const e of this.listeners[t]||[])e({event:t,id:-1,payload:n});return Promise.resolve()}return b(e,t,n)}_handleTauriEvent(e,t){return!!M.includes(e)&&(e in this.listeners?this.listeners[e].push(t):this.listeners[e]=[t],!0)}async position(){return o("plugin:webview|webview_position",{label:this.label}).then((({x:e,y:t})=>new k(e,t)))}async size(){return o("plugin:webview|webview_size",{label:this.label}).then((({width:e,height:t})=>new f(e,t)))}async close(){return o("plugin:webview|close",{label:this.label})}async setSize(e){if(!e||"Logical"!==e.type&&"Physical"!==e.type)throw new Error("the `size` argument must be either a LogicalSize or a PhysicalSize instance");return o("plugin:webview|set_webview_size",{label:this.label,value:{type:e.type,data:{width:e.width,height:e.height}}})}async setPosition(e){if(!e||"Logical"!==e.type&&"Physical"!==e.type)throw new Error("the `position` argument must be either a LogicalPosition or a PhysicalPosition instance");return o("plugin:webview|set_webview_position",{label:this.label,value:{type:e.type,data:{x:e.x,y:e.y}}})}async setFocus(){return o("plugin:webview|set_webview_focus",{label:this.label})}async reparent(e){return o("plugin:webview|set_webview_focus",{label:this.label,window:"string"==typeof e?e:e.label})}async onFileDropEvent(e){const t=await this.listen(d.FILE_DROP,(t=>{e({...t,payload:{type:"drop",paths:t.payload.paths,position:B(t.payload.position)}})})),n=await this.listen(d.FILE_DROP_HOVER,(t=>{e({...t,payload:{type:"hover",paths:t.payload.paths,position:B(t.payload.position)}})})),i=await this.listen(d.FILE_DROP_CANCELLED,(t=>{e({...t,payload:{type:"cancel"}})}));return()=>{t(),n(),i()}}}function B(e){return new k(e.x,e.y)}var V,j,H=Object.freeze({__proto__:null,Webview:U,getAll:N,getCurrent:W});function G(){const e=W();return new Q(e.label,{skip:!0})}function q(){return window.__TAURI_INTERNALS__.metadata.webviews.map((e=>new Q(e.label,{skip:!0})))}class Q{constructor(e,t={}){this.label=e,this.listeners=Object.create(null),t?.skip||o("plugin:webview|create_webview_window",{options:{...t,parent:"string"==typeof t.parent?t.parent:t.parent?.label,label:e}}).then((async()=>this.emit("tauri://created"))).catch((async e=>this.emit("tauri://error",e)))}static getByLabel(e){const t=q().find((t=>t.label===e))??null;return t?new Q(t.label,{skip:!0}):null}static getCurrent(){return G()}static getAll(){return q().map((e=>new Q(e.label,{skip:!0})))}async listen(e,t){return this._handleTauriEvent(e,t)?Promise.resolve((()=>{const n=this.listeners[e];n.splice(n.indexOf(t),1)})):y(e,t,{target:{kind:"WebviewWindow",label:this.label}})}async once(e,t){return this._handleTauriEvent(e,t)?Promise.resolve((()=>{const n=this.listeners[e];n.splice(n.indexOf(t),1)})):w(e,t,{target:{kind:"WebviewWindow",label:this.label}})}}V=Q,j=[T,U],(Array.isArray(j)?j:[j]).forEach((e=>{Object.getOwnPropertyNames(e.prototype).forEach((t=>{"object"==typeof V.prototype&&V.prototype&&t in V.prototype||Object.defineProperty(V.prototype,t,Object.getOwnPropertyDescriptor(e.prototype,t)??Object.create(null))}))}));var $,Z=Object.freeze({__proto__:null,WebviewWindow:Q,getAll:q,getCurrent:G});!function(e){e[e.Audio=1]="Audio",e[e.Cache=2]="Cache",e[e.Config=3]="Config",e[e.Data=4]="Data",e[e.LocalData=5]="LocalData",e[e.Document=6]="Document",e[e.Download=7]="Download",e[e.Picture=8]="Picture",e[e.Public=9]="Public",e[e.Video=10]="Video",e[e.Resource=11]="Resource",e[e.Temp=12]="Temp",e[e.AppConfig=13]="AppConfig",e[e.AppData=14]="AppData",e[e.AppLocalData=15]="AppLocalData",e[e.AppCache=16]="AppCache",e[e.AppLog=17]="AppLog",e[e.Desktop=18]="Desktop",e[e.Executable=19]="Executable",e[e.Font=20]="Font",e[e.Home=21]="Home",e[e.Runtime=22]="Runtime",e[e.Template=23]="Template"}($||($={}));var J=Object.freeze({__proto__:null,get BaseDirectory(){return $},appCacheDir:async function(){return o("plugin:path|resolve_directory",{directory:$.AppCache})},appConfigDir:async function(){return o("plugin:path|resolve_directory",{directory:$.AppConfig})},appDataDir:async function(){return o("plugin:path|resolve_directory",{directory:$.AppData})},appLocalDataDir:async function(){return o("plugin:path|resolve_directory",{directory:$.AppLocalData})},appLogDir:async function(){return o("plugin:path|resolve_directory",{directory:$.AppLog})},audioDir:async function(){return o("plugin:path|resolve_directory",{directory:$.Audio})},basename:async function(e,t){return o("plugin:path|basename",{path:e,ext:t})},cacheDir:async function(){return o("plugin:path|resolve_directory",{directory:$.Cache})},configDir:async function(){return o("plugin:path|resolve_directory",{directory:$.Config})},dataDir:async function(){return o("plugin:path|resolve_directory",{directory:$.Data})},delimiter:function(){return window.__TAURI_INTERNALS__.plugins.path.delimiter},desktopDir:async function(){return o("plugin:path|resolve_directory",{directory:$.Desktop})},dirname:async function(e){return o("plugin:path|dirname",{path:e})},documentDir:async function(){return o("plugin:path|resolve_directory",{directory:$.Document})},downloadDir:async function(){return o("plugin:path|resolve_directory",{directory:$.Download})},executableDir:async function(){return o("plugin:path|resolve_directory",{directory:$.Executable})},extname:async function(e){return o("plugin:path|extname",{path:e})},fontDir:async function(){return o("plugin:path|resolve_directory",{directory:$.Font})},homeDir:async function(){return o("plugin:path|resolve_directory",{directory:$.Home})},isAbsolute:async function(e){return o("plugin:path|isAbsolute",{path:e})},join:async function(...e){return o("plugin:path|join",{paths:e})},localDataDir:async function(){return o("plugin:path|resolve_directory",{directory:$.LocalData})},normalize:async function(e){return o("plugin:path|normalize",{path:e})},pictureDir:async function(){return o("plugin:path|resolve_directory",{directory:$.Picture})},publicDir:async function(){return o("plugin:path|resolve_directory",{directory:$.Public})},resolve:async function(...e){return o("plugin:path|resolve",{paths:e})},resolveResource:async function(e){return o("plugin:path|resolve_directory",{directory:$.Resource,path:e})},resourceDir:async function(){return o("plugin:path|resolve_directory",{directory:$.Resource})},runtimeDir:async function(){return o("plugin:path|resolve_directory",{directory:$.Runtime})},sep:function(){return window.__TAURI_INTERNALS__.plugins.path.sep},tempDir:async function(){return o("plugin:path|resolve_directory",{directory:$.Temp})},templateDir:async function(){return o("plugin:path|resolve_directory",{directory:$.Template})},videoDir:async function(){return o("plugin:path|resolve_directory",{directory:$.Video})}});class K extends u{constructor(e,t){super(e),this.id=t}static async new(e){e?.menu&&(e.menu=[e.menu.rid,e.menu.kind]),e?.icon&&(e.icon="string"==typeof e.icon?e.icon:Array.from(e.icon));const t=new s;return e?.action&&(t.onmessage=e.action,delete e.action),o("plugin:tray|new",{options:e??{},handler:t}).then((([e,t])=>new K(e,t)))}async setIcon(e){let t=null;return e&&(t="string"==typeof e?e:Array.from(e)),o("plugin:tray|set_icon",{rid:this.rid,icon:t})}async setMenu(e){return e&&(e=[e.rid,e.kind]),o("plugin:tray|set_menu",{rid:this.rid,menu:e})}async setTooltip(e){return o("plugin:tray|set_tooltip",{rid:this.rid,tooltip:e})}async setTitle(e){return o("plugin:tray|set_title",{rid:this.rid,title:e})}async setVisible(e){return o("plugin:tray|set_visible",{rid:this.rid,visible:e})}async setTempDirPath(e){return o("plugin:tray|set_temp_dir_path",{rid:this.rid,path:e})}async setIconAsTemplate(e){return o("plugin:tray|set_icon_as_template",{rid:this.rid,asTemplate:e})}async setMenuOnLeftClick(e){return o("plugin:tray|set_show_menu_on_left_click",{rid:this.rid,onLeft:e})}}var Y,X,ee,te=Object.freeze({__proto__:null,TrayIcon:K});function ne(e){if("items"in e)e.items=e.items?.map((e=>"rid"in e?e:ne(e)));else if("action"in e&&e.action){const t=new s;return t.onmessage=e.action,delete e.action,{...e,handler:t}}return e}async function ie(e,t){const n=new s;let i=null;return t&&"object"==typeof t&&("action"in t&&t.action&&(n.onmessage=t.action,delete t.action),"items"in t&&t.items&&(i=t.items.map((e=>"rid"in e?[e.rid,e.kind]:ne(e))))),o("plugin:menu|new",{kind:e,options:t?{...t,items:i}:void 0,handler:n})}class re extends u{get id(){return t(this,Y,"f")}get kind(){return t(this,X,"f")}constructor(e,t,i){super(e),Y.set(this,void 0),X.set(this,void 0),n(this,Y,t,"f"),n(this,X,i,"f")}}Y=new WeakMap,X=new WeakMap;class ae extends re{constructor(e,t){super(e,t,"MenuItem")}static async new(e){return ie("MenuItem",e).then((([e,t])=>new ae(e,t)))}async text(){return o("plugin:menu|text",{rid:this.rid,kind:this.kind})}async setText(e){return o("plugin:menu|set_text",{rid:this.rid,kind:this.kind,text:e})}async isEnabled(){return o("plugin:menu|is_enabled",{rid:this.rid,kind:this.kind})}async setEnabled(e){return o("plugin:menu|set_enabled",{rid:this.rid,kind:this.kind,enabled:e})}async setAccelerator(e){return o("plugin:menu|set_accelerator",{rid:this.rid,kind:this.kind,accelerator:e})}}class se extends re{constructor(e,t){super(e,t,"Check")}static async new(e){return ie("Check",e).then((([e,t])=>new se(e,t)))}async text(){return o("plugin:menu|text",{rid:this.rid,kind:this.kind})}async setText(e){return o("plugin:menu|set_text",{rid:this.rid,kind:this.kind,text:e})}async isEnabled(){return o("plugin:menu|is_enabled",{rid:this.rid,kind:this.kind})}async setEnabled(e){return o("plugin:menu|set_enabled",{rid:this.rid,kind:this.kind,enabled:e})}async setAccelerator(e){return o("plugin:menu|set_accelerator",{rid:this.rid,kind:this.kind,accelerator:e})}async isChecked(){return o("plugin:menu|is_checked",{rid:this.rid})}async setChecked(e){return o("plugin:menu|set_checked",{rid:this.rid,checked:e})}}!function(e){e.Add="Add",e.Advanced="Advanced",e.Bluetooth="Bluetooth",e.Bookmarks="Bookmarks",e.Caution="Caution",e.ColorPanel="ColorPanel",e.ColumnView="ColumnView",e.Computer="Computer",e.EnterFullScreen="EnterFullScreen",e.Everyone="Everyone",e.ExitFullScreen="ExitFullScreen",e.FlowView="FlowView",e.Folder="Folder",e.FolderBurnable="FolderBurnable",e.FolderSmart="FolderSmart",e.FollowLinkFreestanding="FollowLinkFreestanding",e.FontPanel="FontPanel",e.GoLeft="GoLeft",e.GoRight="GoRight",e.Home="Home",e.IChatTheater="IChatTheater",e.IconView="IconView",e.Info="Info",e.InvalidDataFreestanding="InvalidDataFreestanding",e.LeftFacingTriangle="LeftFacingTriangle",e.ListView="ListView",e.LockLocked="LockLocked",e.LockUnlocked="LockUnlocked",e.MenuMixedState="MenuMixedState",e.MenuOnState="MenuOnState",e.MobileMe="MobileMe",e.MultipleDocuments="MultipleDocuments",e.Network="Network",e.Path="Path",e.PreferencesGeneral="PreferencesGeneral",e.QuickLook="QuickLook",e.RefreshFreestanding="RefreshFreestanding",e.Refresh="Refresh",e.Remove="Remove",e.RevealFreestanding="RevealFreestanding",e.RightFacingTriangle="RightFacingTriangle",e.Share="Share",e.Slideshow="Slideshow",e.SmartBadge="SmartBadge",e.StatusAvailable="StatusAvailable",e.StatusNone="StatusNone",e.StatusPartiallyAvailable="StatusPartiallyAvailable",e.StatusUnavailable="StatusUnavailable",e.StopProgressFreestanding="StopProgressFreestanding",e.StopProgress="StopProgress",e.TrashEmpty="TrashEmpty",e.TrashFull="TrashFull",e.User="User",e.UserAccounts="UserAccounts",e.UserGroup="UserGroup",e.UserGuest="UserGuest"}(ee||(ee={}));class le extends re{constructor(e,t){super(e,t,"Icon")}static async new(e){return ie("Icon",e).then((([e,t])=>new le(e,t)))}async text(){return o("plugin:menu|text",{rid:this.rid,kind:this.kind})}async setText(e){return o("plugin:menu|set_text",{rid:this.rid,kind:this.kind,text:e})}async isEnabled(){return o("plugin:menu|is_enabled",{rid:this.rid,kind:this.kind})}async setEnabled(e){return o("plugin:menu|set_enabled",{rid:this.rid,kind:this.kind,enabled:e})}async setAccelerator(e){return o("plugin:menu|set_accelerator",{rid:this.rid,kind:this.kind,accelerator:e})}async setIcon(e){return o("plugin:menu|set_icon",{rid:this.rid,icon:e})}}class oe extends re{constructor(e,t){super(e,t,"Predefined")}static async new(e){return ie("Predefined",e).then((([e,t])=>new oe(e,t)))}async text(){return o("plugin:menu|text",{rid:this.rid,kind:this.kind})}async setText(e){return o("plugin:menu|set_text",{rid:this.rid,kind:this.kind,text:e})}}function ue([e,t,n]){switch(n){case"Submenu":return new ce(e,t);case"Predefined":return new oe(e,t);case"Check":return new se(e,t);case"Icon":return new le(e,t);default:return new ae(e,t)}}class ce extends re{constructor(e,t){super(e,t,"Submenu")}static async new(e){return ie("Submenu",e).then((([e,t])=>new ce(e,t)))}async text(){return o("plugin:menu|text",{rid:this.rid,kind:this.kind})}async setText(e){return o("plugin:menu|set_text",{rid:this.rid,kind:this.kind,text:e})}async isEnabled(){return o("plugin:menu|is_enabled",{rid:this.rid,kind:this.kind})}async setEnabled(e){return o("plugin:menu|set_enabled",{rid:this.rid,kind:this.kind,enabled:e})}async append(e){return o("plugin:menu|append",{rid:this.rid,kind:this.kind,items:(Array.isArray(e)?e:[e]).map((e=>"rid"in e?[e.rid,e.kind]:e))})}async prepend(e){return o("plugin:menu|prepend",{rid:this.rid,kind:this.kind,items:(Array.isArray(e)?e:[e]).map((e=>"rid"in e?[e.rid,e.kind]:e))})}async insert(e,t){return o("plugin:menu|insert",{rid:this.rid,kind:this.kind,items:(Array.isArray(e)?e:[e]).map((e=>"rid"in e?[e.rid,e.kind]:e)),position:t})}async remove(e){return o("plugin:menu|remove",{rid:this.rid,kind:this.kind,item:[e.rid,e.kind]})}async removeAt(e){return o("plugin:menu|remove_at",{rid:this.rid,kind:this.kind,position:e}).then(ue)}async items(){return o("plugin:menu|items",{rid:this.rid,kind:this.kind}).then((e=>e.map(ue)))}async get(e){return o("plugin:menu|get",{rid:this.rid,kind:this.kind,id:e}).then((e=>e?ue(e):null))}async popup(e,t){let n=null;return e&&(n={type:e instanceof k?"Physical":"Logical",data:e}),o("plugin:menu|popup",{rid:this.rid,kind:this.kind,window:t?.label??null,at:n})}async setAsWindowsMenuForNSApp(){return o("plugin:menu|set_as_windows_menu_for_nsapp",{rid:this.rid})}async setAsHelpMenuForNSApp(){return o("plugin:menu|set_as_help_menu_for_nsapp",{rid:this.rid})}}function de([e,t,n]){switch(n){case"Submenu":return new ce(e,t);case"Predefined":return new oe(e,t);case"Check":return new se(e,t);case"Icon":return new le(e,t);default:return new ae(e,t)}}class pe extends re{constructor(e,t){super(e,t,"Menu")}static async new(e){return ie("Menu",e).then((([e,t])=>new pe(e,t)))}static async default(){return o("plugin:menu|create_default").then((([e,t])=>new pe(e,t)))}async append(e){return o("plugin:menu|append",{rid:this.rid,kind:this.kind,items:(Array.isArray(e)?e:[e]).map((e=>"rid"in e?[e.rid,e.kind]:e))})}async prepend(e){return o("plugin:menu|prepend",{rid:this.rid,kind:this.kind,items:(Array.isArray(e)?e:[e]).map((e=>"rid"in e?[e.rid,e.kind]:e))})}async insert(e,t){return o("plugin:menu|insert",{rid:this.rid,kind:this.kind,items:(Array.isArray(e)?e:[e]).map((e=>"rid"in e?[e.rid,e.kind]:e)),position:t})}async remove(e){return o("plugin:menu|remove",{rid:this.rid,kind:this.kind,item:[e.rid,e.kind]})}async removeAt(e){return o("plugin:menu|remove_at",{rid:this.rid,kind:this.kind,position:e}).then(de)}async items(){return o("plugin:menu|items",{rid:this.rid,kind:this.kind}).then((e=>e.map(de)))}async get(e){return o("plugin:menu|get",{rid:this.rid,kind:this.kind,id:e}).then((e=>e?de(e):null))}async popup(e,t){let n=null;return e&&(n={type:e instanceof k?"Physical":"Logical",data:e}),o("plugin:menu|popup",{rid:this.rid,kind:this.kind,window:t?.label??null,at:n})}async setAsAppMenu(){return o("plugin:menu|set_as_app_menu",{rid:this.rid}).then((e=>e?new pe(e[0],e[1]):null))}async setAsWindowMenu(e){return o("plugin:menu|set_as_window_menu",{rid:this.rid,window:e?.label??null}).then((e=>e?new pe(e[0],e[1]):null))}}var he=Object.freeze({__proto__:null,CheckMenuItem:se,IconMenuItem:le,Menu:pe,MenuItem:ae,get NativeIcon(){return ee},PredefinedMenuItem:oe,Submenu:ce});return e.app=p,e.core=c,e.dpi=D,e.event=_,e.menu=he,e.path=J,e.tray=te,e.webview=H,e.webviewWindow=Z,e.window=O,e}({});window.__TAURI__=__TAURI_IIFE__; diff --git a/core/tauri/src/ipc/protocol.rs b/core/tauri/src/ipc/protocol.rs index e9acaf8a0..e3e29495d 100644 --- a/core/tauri/src/ipc/protocol.rs +++ b/core/tauri/src/ipc/protocol.rs @@ -244,11 +244,13 @@ fn handle_ipc_message(message: String, manager: &AppManager, labe } } - match invoke_message.unwrap_or_else(|| { + let message = invoke_message.unwrap_or_else(|| { #[cfg(feature = "tracing")] let _span = tracing::trace_span!("ipc::request::deserialize").entered(); serde_json::from_str::(&message).map_err(Into::into) - }) { + }); + + match message { Ok(message) => { let request = InvokeRequest { cmd: message.cmd, diff --git a/core/tauri/src/test/mock_runtime.rs b/core/tauri/src/test/mock_runtime.rs index e9342cb01..38c6b1fa2 100644 --- a/core/tauri/src/test/mock_runtime.rs +++ b/core/tauri/src/test/mock_runtime.rs @@ -540,6 +540,10 @@ impl WebviewDispatch for MockWebviewDispatcher { fn set_focus(&self) -> Result<()> { Ok(()) } + + fn reparent(&self, window_id: WindowId) -> Result<()> { + Ok(()) + } } impl WindowDispatch for MockWindowDispatcher { diff --git a/core/tauri/src/webview/mod.rs b/core/tauri/src/webview/mod.rs index 7a20d675b..cc0b673d7 100644 --- a/core/tauri/src/webview/mod.rs +++ b/core/tauri/src/webview/mod.rs @@ -606,7 +606,7 @@ tauri::Builder::default() .webviews_lock() .values() .map(|w| WebviewLabelDef { - window_label: w.window.label().to_string(), + window_label: w.window().label().to_string(), label: w.label().to_string(), }) .collect::>(); @@ -794,7 +794,10 @@ fn main() { /// Webview. #[default_runtime(crate::Wry, wry)] pub struct Webview { - pub(crate) window: Window, + window_label: Arc>, + /// The manager to associate this webview with. + pub(crate) manager: Arc>, + pub(crate) app_handle: AppHandle, /// The webview created by the runtime. pub(crate) webview: DetachedWebview, } @@ -802,7 +805,7 @@ pub struct Webview { impl std::fmt::Debug for Webview { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("Window") - .field("window", &self.window) + .field("window_label", &self.window_label) .field("webview", &self.webview) .finish() } @@ -811,7 +814,9 @@ impl std::fmt::Debug for Webview { impl Clone for Webview { fn clone(&self) -> Self { Self { - window: self.window.clone(), + window_label: self.window_label.clone(), + manager: self.manager.clone(), + app_handle: self.app_handle.clone(), webview: self.webview.clone(), } } @@ -836,7 +841,12 @@ impl PartialEq for Webview { impl Webview { /// Create a new webview that is attached to the window. pub(crate) fn new(window: Window, webview: DetachedWebview) -> Self { - Self { window, webview } + Self { + window_label: Arc::new(Mutex::new(window.label().into())), + manager: window.manager.clone(), + app_handle: window.app_handle.clone(), + webview, + } } /// Initializes a webview builder with the given window label and URL to load on the webview. @@ -883,8 +893,9 @@ impl Webview { /// Closes this webview. pub fn close(&self) -> crate::Result<()> { - if self.window.is_webview_window { - self.window.close() + let window = self.window(); + if window.is_webview_window { + window.close() } else { self.webview.dispatcher.close()?; self.manager().on_webview_close(self.label()); @@ -894,8 +905,9 @@ impl Webview { /// Resizes this webview. pub fn set_size>(&self, size: S) -> crate::Result<()> { - if self.window.is_webview_window { - self.window.set_size(size.into()) + let window = self.window(); + if window.is_webview_window { + window.set_size(size.into()) } else { self .webview @@ -907,8 +919,9 @@ impl Webview { /// Sets this webviews's position. pub fn set_position>(&self, position: Pos) -> crate::Result<()> { - if self.window.is_webview_window { - self.window.set_position(position.into()) + let window = self.window(); + if window.is_webview_window { + window.set_position(position.into()) } else { self .webview @@ -923,13 +936,23 @@ impl Webview { self.webview.dispatcher.set_focus().map_err(Into::into) } + /// Move the webview to the given window. + pub fn reparent(&self, window: &Window) -> crate::Result<()> { + let current_window = self.window(); + if !current_window.is_webview_window { + self.webview.dispatcher.reparent(window.window.id)?; + } + Ok(()) + } + /// Returns the webview position. /// /// - For child webviews, returns the position of the top-left hand corner of the webviews's client area relative to the top-left hand corner of the parent window. /// - For webview window, returns the inner position of the window. pub fn position(&self) -> crate::Result> { - if self.window.is_webview_window { - self.window.inner_position() + let window = self.window(); + if window.is_webview_window { + window.inner_position() } else { self.webview.dispatcher.position().map_err(Into::into) } @@ -937,8 +960,9 @@ impl Webview { /// Returns the physical size of the webviews's client area. pub fn size(&self) -> crate::Result> { - if self.window.is_webview_window { - self.window.inner_size() + let window = self.window(); + if window.is_webview_window { + window.inner_size() } else { self.webview.dispatcher.size().map_err(Into::into) } @@ -948,8 +972,11 @@ impl Webview { /// Webview APIs. impl Webview { /// The window that is hosting this webview. - pub fn window(&self) -> &Window { - &self.window + pub fn window(&self) -> Window { + self + .manager + .get_window(&self.window_label.lock().unwrap()) + .expect("could not locate webview parent window") } /// Executes a closure, providing it with the webview handle that is specific to the current platform. @@ -1099,7 +1126,7 @@ fn main() { ); #[cfg(mobile)] - let app_handle = self.window.app_handle.clone(); + let app_handle = self.app_handle.clone(); let message = InvokeMessage::new( self, @@ -1415,7 +1442,7 @@ tauri::Builder::default() where F: Fn(Event) + Send + 'static, { - self.window.manager.listen( + self.manager.listen( event.into(), EventTarget::Webview { label: self.label().to_string(), @@ -1454,7 +1481,7 @@ tauri::Builder::default() "#### )] pub fn unlisten(&self, id: EventId) { - self.window.manager.unlisten(id) + self.manager.unlisten(id) } /// Listen to an event on this webview only once. @@ -1464,7 +1491,7 @@ tauri::Builder::default() where F: FnOnce(Event) + Send + 'static, { - self.window.manager.once( + self.manager.once( event.into(), EventTarget::Webview { label: self.label().to_string(), @@ -1478,19 +1505,19 @@ impl Manager for Webview {} impl ManagerBase for Webview { fn manager(&self) -> &AppManager { - &self.window.manager + &self.manager } fn manager_owned(&self) -> Arc> { - self.window.manager.clone() + self.manager.clone() } fn runtime(&self) -> RuntimeOrDispatch<'_, R> { - self.window.app_handle.runtime() + self.app_handle.runtime() } fn managed_app_handle(&self) -> &AppHandle { - &self.window.app_handle + &self.app_handle } } diff --git a/core/tauri/src/webview/plugin.rs b/core/tauri/src/webview/plugin.rs index 9e0ed5334..c26decce8 100644 --- a/core/tauri/src/webview/plugin.rs +++ b/core/tauri/src/webview/plugin.rs @@ -159,6 +159,19 @@ mod desktop_commands { setter!(set_webview_position, set_position, Position); setter!(set_webview_focus, set_focus); + #[command(root = "crate")] + pub async fn reparent( + webview: crate::Webview, + label: Option, + window: String, + ) -> crate::Result<()> { + let webview = get_webview(webview, label)?; + if let Some(window) = webview.manager.get_window(&window) { + webview.reparent(&window)?; + } + Ok(()) + } + #[cfg(any(debug_assertions, feature = "devtools"))] #[command(root = "crate")] pub async fn internal_toggle_devtools( @@ -227,6 +240,7 @@ pub fn init() -> TauriPlugin { desktop_commands::set_webview_position, desktop_commands::set_webview_focus, desktop_commands::print, + desktop_commands::reparent, #[cfg(any(debug_assertions, feature = "devtools"))] desktop_commands::internal_toggle_devtools, ]); diff --git a/core/tauri/src/webview/webview_window.rs b/core/tauri/src/webview/webview_window.rs index 58ffc1b4e..de4c7d830 100644 --- a/core/tauri/src/webview/webview_window.rs +++ b/core/tauri/src/webview/webview_window.rs @@ -572,7 +572,7 @@ impl<'a, R: Runtime, M: Manager> WebviewWindowBuilder<'a, R, M> { /// - **Linux**: This makes the new window transient for parent, see /// - **macOS**: This adds the window as a child of parent, see pub fn parent(mut self, parent: &WebviewWindow) -> crate::Result { - self.window_builder = self.window_builder.parent(&parent.webview.window)?; + self.window_builder = self.window_builder.parent(&parent.webview.window())?; Ok(self) } @@ -586,7 +586,7 @@ impl<'a, R: Runtime, M: Manager> WebviewWindowBuilder<'a, R, M> { /// For more information, see #[cfg(windows)] pub fn owner(mut self, owner: &WebviewWindow) -> crate::Result { - self.window_builder = self.window_builder.owner(&owner.webview.window)?; + self.window_builder = self.window_builder.owner(&owner.webview.window())?; Ok(self) } @@ -638,7 +638,9 @@ impl<'a, R: Runtime, M: Manager> WebviewWindowBuilder<'a, R, M> { target_os = "openbsd" ))] pub fn transient_for(mut self, parent: &WebviewWindow) -> crate::Result { - self.window_builder = self.window_builder.transient_for(&parent.webview.window)?; + self.window_builder = self + .window_builder + .transient_for(&parent.webview.window())?; Ok(self) } @@ -868,7 +870,9 @@ impl raw_window_handle::HasWindowHandle for WebviewWindow { fn window_handle( &self, ) -> std::result::Result, raw_window_handle::HandleError> { - self.webview.window().window_handle() + Ok(unsafe { + raw_window_handle::WindowHandle::borrow_raw(self.webview.window().window_handle()?.as_raw()) + }) } } diff --git a/core/tauri/src/window/mod.rs b/core/tauri/src/window/mod.rs index e06b557a5..aaf4f5e0e 100644 --- a/core/tauri/src/window/mod.rs +++ b/core/tauri/src/window/mod.rs @@ -333,7 +333,7 @@ tauri::Builder::default() .webviews_lock() .values() .map(|w| WebviewLabelDef { - window_label: w.window.label().to_string(), + window_label: w.window().label().to_string(), label: w.label().to_string(), }) .collect::>(); @@ -988,7 +988,7 @@ impl Window { .webview .webviews_lock() .values() - .filter(|w| w.window() == self) + .filter(|w| &w.window() == self) .cloned() .collect() } diff --git a/tooling/api/src/webview.ts b/tooling/api/src/webview.ts index 72d9edf50..3200ed72c 100644 --- a/tooling/api/src/webview.ts +++ b/tooling/api/src/webview.ts @@ -31,6 +31,7 @@ import { } from './event' import { invoke } from './core' import { Window, getCurrent as getCurrentWindow } from './window' +import { WebviewWindow } from './webviewWindow' interface FileDropPayload { paths: string[] @@ -474,6 +475,23 @@ class Webview { }) } + /** + * Moves this webview to the given label. + * @example + * ```typescript + * import { getCurrent } from '@tauri-apps/api/webview'; + * await getCurrent().reparent('other-window'); + * ``` + * + * @returns A promise indicating the success or failure of the operation. + */ + async reparent(window: Window | WebviewWindow | string): Promise { + return invoke('plugin:webview|set_webview_focus', { + label: this.label, + window: typeof window === 'string' ? window : window.label + }) + } + // Listeners /**