@@ -59,6 +59,7 @@ type SetupWithConfigHook<R, T> = dyn FnOnce(&AppHandle<R>, T) -> Result<()> + Se
5959type OnWebviewReady < R > = dyn FnMut ( Window < R > ) + Send ;
6060type OnEvent < R > = dyn FnMut ( & AppHandle < R > , & RunEvent ) + Send ;
6161type OnPageLoad < R > = dyn FnMut ( Window < R > , PageLoadPayload ) + Send ;
62+ type OnDrop < R > = dyn FnOnce ( AppHandle < R > ) + Send ;
6263
6364/// Builds a [`TauriPlugin`].
6465///
@@ -141,6 +142,7 @@ pub struct Builder<R: Runtime, C: DeserializeOwned = ()> {
141142 on_page_load : Box < OnPageLoad < R > > ,
142143 on_webview_ready : Box < OnWebviewReady < R > > ,
143144 on_event : Box < OnEvent < R > > ,
145+ on_drop : Option < Box < OnDrop < R > > > ,
144146}
145147
146148impl < R : Runtime , C : DeserializeOwned > Builder < R , C > {
@@ -155,6 +157,7 @@ impl<R: Runtime, C: DeserializeOwned> Builder<R, C> {
155157 on_page_load : Box :: new ( |_, _| ( ) ) ,
156158 on_webview_ready : Box :: new ( |_| ( ) ) ,
157159 on_event : Box :: new ( |_, _| ( ) ) ,
160+ on_drop : None ,
158161 }
159162 }
160163
@@ -311,7 +314,7 @@ impl<R: Runtime, C: DeserializeOwned> Builder<R, C> {
311314 #[ must_use]
312315 pub fn on_page_load < F > ( mut self , on_page_load : F ) -> Self
313316 where
314- F : FnMut ( Window < R > , PageLoadPayload ) + Send + Sync + ' static ,
317+ F : FnMut ( Window < R > , PageLoadPayload ) + Send + ' static ,
315318 {
316319 self . on_page_load = Box :: new ( on_page_load) ;
317320 self
@@ -335,7 +338,7 @@ impl<R: Runtime, C: DeserializeOwned> Builder<R, C> {
335338 #[ must_use]
336339 pub fn on_webview_ready < F > ( mut self , on_webview_ready : F ) -> Self
337340 where
338- F : FnMut ( Window < R > ) + Send + Sync + ' static ,
341+ F : FnMut ( Window < R > ) + Send + ' static ,
339342 {
340343 self . on_webview_ready = Box :: new ( on_webview_ready) ;
341344 self
@@ -367,37 +370,74 @@ impl<R: Runtime, C: DeserializeOwned> Builder<R, C> {
367370 #[ must_use]
368371 pub fn on_event < F > ( mut self , on_event : F ) -> Self
369372 where
370- F : FnMut ( & AppHandle < R > , & RunEvent ) + Send + Sync + ' static ,
373+ F : FnMut ( & AppHandle < R > , & RunEvent ) + Send + ' static ,
371374 {
372375 self . on_event = Box :: new ( on_event) ;
373376 self
374377 }
375378
379+ /// Callback invoked when the plugin is dropped.
380+ ///
381+ /// # Examples
382+ ///
383+ /// ```rust
384+ /// use tauri::{plugin::{Builder, TauriPlugin}, Runtime};
385+ ///
386+ /// fn init<R: Runtime>() -> TauriPlugin<R> {
387+ /// Builder::new("example")
388+ /// .on_drop(|app| {
389+ /// println!("plugin has been dropped and is no longer running");
390+ /// // you can run cleanup logic here
391+ /// })
392+ /// .build()
393+ /// }
394+ /// ```
395+ #[ must_use]
396+ pub fn on_drop < F > ( mut self , on_drop : F ) -> Self
397+ where
398+ F : FnOnce ( AppHandle < R > ) + Send + ' static ,
399+ {
400+ self . on_drop . replace ( Box :: new ( on_drop) ) ;
401+ self
402+ }
403+
376404 /// Builds the [TauriPlugin].
377405 pub fn build ( self ) -> TauriPlugin < R , C > {
378406 TauriPlugin {
379407 name : self . name ,
408+ app : None ,
380409 invoke_handler : self . invoke_handler ,
381410 setup : self . setup ,
382411 setup_with_config : self . setup_with_config ,
383412 js_init_script : self . js_init_script ,
384413 on_page_load : self . on_page_load ,
385414 on_webview_ready : self . on_webview_ready ,
386415 on_event : self . on_event ,
416+ on_drop : self . on_drop ,
387417 }
388418 }
389419}
390420
391421/// Plugin struct that is returned by the [`Builder`]. Should only be constructed through the builder.
392422pub struct TauriPlugin < R : Runtime , C : DeserializeOwned = ( ) > {
393423 name : & ' static str ,
424+ app : Option < AppHandle < R > > ,
394425 invoke_handler : Box < InvokeHandler < R > > ,
395426 setup : Option < Box < SetupHook < R > > > ,
396427 setup_with_config : Option < Box < SetupWithConfigHook < R , C > > > ,
397428 js_init_script : Option < String > ,
398429 on_page_load : Box < OnPageLoad < R > > ,
399430 on_webview_ready : Box < OnWebviewReady < R > > ,
400431 on_event : Box < OnEvent < R > > ,
432+ on_drop : Option < Box < OnDrop < R > > > ,
433+ }
434+
435+ impl < R : Runtime , C : DeserializeOwned > Drop for TauriPlugin < R , C > {
436+ fn drop ( & mut self ) {
437+ if let ( Some ( on_drop) , Some ( app) ) = ( self . on_drop . take ( ) , self . app . take ( ) ) {
438+ on_drop ( app) ;
439+ }
440+ }
401441}
402442
403443impl < R : Runtime , C : DeserializeOwned > Plugin < R > for TauriPlugin < R , C > {
@@ -406,6 +446,7 @@ impl<R: Runtime, C: DeserializeOwned> Plugin<R> for TauriPlugin<R, C> {
406446 }
407447
408448 fn initialize ( & mut self , app : & AppHandle < R > , config : JsonValue ) -> Result < ( ) > {
449+ self . app . replace ( app. clone ( ) ) ;
409450 if let Some ( s) = self . setup . take ( ) {
410451 ( s) ( app) ?;
411452 }
@@ -466,6 +507,11 @@ impl<R: Runtime> PluginStore<R> {
466507 self . store . insert ( plugin. name ( ) , Box :: new ( plugin) ) . is_some ( )
467508 }
468509
510+ /// Removes the plugin with the given name from the store.
511+ pub fn unregister ( & mut self , plugin : & ' static str ) -> bool {
512+ self . store . remove ( plugin) . is_some ( )
513+ }
514+
469515 /// Initializes all plugins in the store.
470516 pub ( crate ) fn initialize (
471517 & mut self ,
0 commit comments