Pārlūkot izejas kodu

feat: `plugin::Builder` closes #2959 (#3005)

Co-authored-by: Amr Bashir <48618675+amrbashir@users.noreply.github.com>
Co-authored-by: Lucas Nogueira <lucas@tauri.studio>
Jonas Kruckenberg 3 gadi atpakaļ
vecāks
revīzija
9aed299621
2 mainītis faili ar 146 papildinājumiem un 2 dzēšanām
  1. 5 0
      .changes/plugin-builder.md
  2. 141 2
      core/tauri/src/plugin.rs

+ 5 - 0
.changes/plugin-builder.md

@@ -0,0 +1,5 @@
+---
+"tauri": minor
+---
+
+Add a `plugin::Builder` struct to make plugin creation more convenient.

+ 141 - 2
core/tauri/src/plugin.rs

@@ -5,8 +5,8 @@
 //! The Tauri plugin extension to expand Tauri functionality.
 
 use crate::{
-  runtime::Runtime, utils::config::PluginConfig, AppHandle, Invoke, PageLoadPayload, RunEvent,
-  Window,
+  runtime::Runtime, utils::config::PluginConfig, AppHandle, Invoke, InvokeHandler, OnPageLoad,
+  PageLoadPayload, RunEvent, Window,
 };
 use serde_json::Value as JsonValue;
 use tauri_macros::default_runtime;
@@ -53,6 +53,145 @@ pub trait Plugin<R: Runtime>: Send {
   fn extend_api(&mut self, invoke: Invoke<R>) {}
 }
 
+type SetupHook<R> = dyn Fn(&AppHandle<R>) -> Result<()> + Send + Sync;
+type OnWebviewReady<R> = dyn Fn(Window<R>) + Send + Sync;
+type OnEvent<R> = dyn Fn(&AppHandle<R>, &RunEvent) + Send + Sync;
+
+/// Builds a [`TauriPlugin`].
+pub struct Builder<R: Runtime> {
+  name: &'static str,
+  invoke_handler: Box<InvokeHandler<R>>,
+  setup: Box<SetupHook<R>>,
+  js_init_script: Option<String>,
+  on_page_load: Box<OnPageLoad<R>>,
+  on_webview_ready: Box<OnWebviewReady<R>>,
+  on_event: Box<OnEvent<R>>,
+}
+
+impl<R: Runtime> Builder<R> {
+  /// Creates a new Plugin builder.
+  pub fn new(name: &'static str) -> Self {
+    Self {
+      name,
+      setup: Box::new(|_| Ok(())),
+      js_init_script: None,
+      invoke_handler: Box::new(|_| ()),
+      on_page_load: Box::new(|_, _| ()),
+      on_webview_ready: Box::new(|_| ()),
+      on_event: Box::new(|_, _| ()),
+    }
+  }
+
+  /// Defines the JS message handler callback.
+  pub fn invoke_handler<F>(mut self, invoke_handler: F) -> Self
+  where
+    F: Fn(Invoke<R>) + Send + Sync + 'static,
+  {
+    self.invoke_handler = Box::new(invoke_handler);
+    self
+  }
+
+  /// The JS script to evaluate on webview initialization.
+  /// The script is wrapped into its own context with `(function () { /* your script here */ })();`,
+  /// so global variables must be assigned to `window` instead of implicity declared.
+  ///
+  /// It's guaranteed that this script is executed before the page is loaded.
+  pub fn js_init_script(mut self, js_init_script: String) -> Self {
+    self.js_init_script = Some(js_init_script);
+    self
+  }
+
+  /// Define a closure that can setup plugin specific state.
+  pub fn setup<F>(mut self, setup: F) -> Self
+  where
+    F: Fn(&AppHandle<R>) -> Result<()> + Send + Sync + 'static,
+  {
+    self.setup = Box::new(setup);
+    self
+  }
+
+  /// Callback invoked when the webview performs a navigation to a page.
+  pub fn on_page_load<F>(mut self, on_page_load: F) -> Self
+  where
+    F: Fn(Window<R>, PageLoadPayload) + Send + Sync + 'static,
+  {
+    self.on_page_load = Box::new(on_page_load);
+    self
+  }
+
+  /// Callback invoked when the webview is created.
+  pub fn on_webview_ready<F>(mut self, on_webview_ready: F) -> Self
+  where
+    F: Fn(Window<R>) + Send + Sync + 'static,
+  {
+    self.on_webview_ready = Box::new(on_webview_ready);
+    self
+  }
+
+  /// Callback invoked when the event loop receives a new event.
+  pub fn on_event<F>(mut self, on_event: F) -> Self
+  where
+    F: Fn(&AppHandle<R>, &RunEvent) + Send + Sync + 'static,
+  {
+    self.on_event = Box::new(on_event);
+    self
+  }
+
+  /// Builds the [TauriPlugin].
+  pub fn build(self) -> TauriPlugin<R> {
+    TauriPlugin {
+      name: self.name,
+      invoke_handler: self.invoke_handler,
+      setup: self.setup,
+      js_init_script: self.js_init_script,
+      on_page_load: self.on_page_load,
+      on_webview_ready: self.on_webview_ready,
+      on_event: self.on_event,
+    }
+  }
+}
+
+/// Plugin struct that is returned by the [`PluginBuilder`]. Should only be constructed through the builder.
+pub struct TauriPlugin<R: Runtime> {
+  name: &'static str,
+  invoke_handler: Box<InvokeHandler<R>>,
+  setup: Box<SetupHook<R>>,
+  js_init_script: Option<String>,
+  on_page_load: Box<OnPageLoad<R>>,
+  on_webview_ready: Box<OnWebviewReady<R>>,
+  on_event: Box<OnEvent<R>>,
+}
+
+impl<R: Runtime> Plugin<R> for TauriPlugin<R> {
+  fn name(&self) -> &'static str {
+    self.name
+  }
+
+  fn initialize(&mut self, app: &AppHandle<R>, _: JsonValue) -> Result<()> {
+    (self.setup)(app)
+  }
+
+  fn initialization_script(&self) -> Option<String> {
+    self.js_init_script.clone()
+  }
+
+  fn created(&mut self, window: Window<R>) {
+    (self.on_webview_ready)(window)
+  }
+
+  fn on_page_load(&mut self, window: Window<R>, payload: PageLoadPayload) {
+    (self.on_page_load)(window, payload)
+  }
+
+  fn on_event(&mut self, app: &AppHandle<R>, event: &RunEvent) {
+    (self.on_event)(app, event)
+  }
+
+  fn extend_api(&mut self, invoke: Invoke<R>) {
+    (self.invoke_handler)(invoke)
+  }
+}
+
 /// Plugin collection type.
 #[default_runtime(crate::Wry, wry)]
 pub(crate) struct PluginStore<R: Runtime> {