diff --git a/.changes/fix-once-fnonce.md b/.changes/fix-once-fnonce.md new file mode 100644 index 000000000..fd167c1d4 --- /dev/null +++ b/.changes/fix-once-fnonce.md @@ -0,0 +1,5 @@ +--- +"tauri": patch +--- + +`Manager::once_global` and `Window::once` allow `FnOnce` callbacks. diff --git a/core/tauri/src/event.rs b/core/tauri/src/event.rs index 82d125562..d7214c5ee 100644 --- a/core/tauri/src/event.rs +++ b/core/tauri/src/event.rs @@ -4,6 +4,7 @@ use std::{ boxed::Box, + cell::Cell, collections::HashMap, fmt, hash::Hash, @@ -170,16 +171,21 @@ impl Listeners { } /// Listen to a JS event and immediately unlisten. - pub(crate) fn once( + pub(crate) fn once( &self, event: String, window: Option, handler: F, ) -> EventHandler { let self_ = self.clone(); + let handler = Cell::new(Some(handler)); + self.listen(event, window, move |event| { self_.unlisten(event.id); - handler(event); + let handler = handler + .take() + .expect("attempted to call handler more than once"); + handler(event) }) } diff --git a/core/tauri/src/lib.rs b/core/tauri/src/lib.rs index 99e664036..eb0ae77c1 100644 --- a/core/tauri/src/lib.rs +++ b/core/tauri/src/lib.rs @@ -427,7 +427,7 @@ pub trait Manager: sealed::ManagerBase { /// Listen to a global event only once. fn once_global(&self, event: impl Into, handler: F) -> EventHandler where - F: Fn(Event) + Send + 'static, + F: FnOnce(Event) + Send + 'static, { self.manager().once(event.into(), None, handler) } diff --git a/core/tauri/src/manager.rs b/core/tauri/src/manager.rs index 7283432d7..8f8315f90 100644 --- a/core/tauri/src/manager.rs +++ b/core/tauri/src/manager.rs @@ -1176,7 +1176,7 @@ impl WindowManager { self.inner.listeners.listen(event, window, handler) } - pub fn once( + pub fn once( &self, event: String, window: Option, diff --git a/core/tauri/src/updater/mod.rs b/core/tauri/src/updater/mod.rs index aea8f65f5..4c0465216 100644 --- a/core/tauri/src/updater/mod.rs +++ b/core/tauri/src/updater/mod.rs @@ -480,7 +480,6 @@ pub(crate) fn listener( window.once(EVENT_INSTALL_UPDATE, move |_msg| { let window = window_isolation.clone(); let updater = updater.clone(); - let pubkey = pubkey.clone(); // Start installation crate::async_runtime::spawn(async move { diff --git a/core/tauri/src/window.rs b/core/tauri/src/window.rs index a625f4e0a..f86b5be23 100644 --- a/core/tauri/src/window.rs +++ b/core/tauri/src/window.rs @@ -321,7 +321,7 @@ impl Window { /// Listen to an event on this window a single time. pub fn once(&self, event: impl Into, handler: F) -> EventHandler where - F: Fn(Event) + Send + 'static, + F: FnOnce(Event) + Send + 'static, { let label = self.window.label.clone(); self.manager.once(event.into(), Some(label), handler)