Skip to content

Commit 9aed299

Browse files
JonasKruckenbergamrbashirlucasfernog
authored
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>
1 parent 10e3190 commit 9aed299

2 files changed

Lines changed: 146 additions & 2 deletions

File tree

.changes/plugin-builder.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"tauri": minor
3+
---
4+
5+
Add a `plugin::Builder` struct to make plugin creation more convenient.

core/tauri/src/plugin.rs

Lines changed: 141 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
//! The Tauri plugin extension to expand Tauri functionality.
66
77
use crate::{
8-
runtime::Runtime, utils::config::PluginConfig, AppHandle, Invoke, PageLoadPayload, RunEvent,
9-
Window,
8+
runtime::Runtime, utils::config::PluginConfig, AppHandle, Invoke, InvokeHandler, OnPageLoad,
9+
PageLoadPayload, RunEvent, Window,
1010
};
1111
use serde_json::Value as JsonValue;
1212
use tauri_macros::default_runtime;
@@ -53,6 +53,145 @@ pub trait Plugin<R: Runtime>: Send {
5353
fn extend_api(&mut self, invoke: Invoke<R>) {}
5454
}
5555

56+
type SetupHook<R> = dyn Fn(&AppHandle<R>) -> Result<()> + Send + Sync;
57+
type OnWebviewReady<R> = dyn Fn(Window<R>) + Send + Sync;
58+
type OnEvent<R> = dyn Fn(&AppHandle<R>, &RunEvent) + Send + Sync;
59+
60+
/// Builds a [`TauriPlugin`].
61+
pub struct Builder<R: Runtime> {
62+
name: &'static str,
63+
invoke_handler: Box<InvokeHandler<R>>,
64+
setup: Box<SetupHook<R>>,
65+
js_init_script: Option<String>,
66+
on_page_load: Box<OnPageLoad<R>>,
67+
on_webview_ready: Box<OnWebviewReady<R>>,
68+
on_event: Box<OnEvent<R>>,
69+
}
70+
71+
impl<R: Runtime> Builder<R> {
72+
/// Creates a new Plugin builder.
73+
pub fn new(name: &'static str) -> Self {
74+
Self {
75+
name,
76+
setup: Box::new(|_| Ok(())),
77+
js_init_script: None,
78+
invoke_handler: Box::new(|_| ()),
79+
on_page_load: Box::new(|_, _| ()),
80+
on_webview_ready: Box::new(|_| ()),
81+
on_event: Box::new(|_, _| ()),
82+
}
83+
}
84+
85+
/// Defines the JS message handler callback.
86+
pub fn invoke_handler<F>(mut self, invoke_handler: F) -> Self
87+
where
88+
F: Fn(Invoke<R>) + Send + Sync + 'static,
89+
{
90+
self.invoke_handler = Box::new(invoke_handler);
91+
self
92+
}
93+
94+
/// The JS script to evaluate on webview initialization.
95+
/// The script is wrapped into its own context with `(function () { /* your script here */ })();`,
96+
/// so global variables must be assigned to `window` instead of implicity declared.
97+
///
98+
/// It's guaranteed that this script is executed before the page is loaded.
99+
pub fn js_init_script(mut self, js_init_script: String) -> Self {
100+
self.js_init_script = Some(js_init_script);
101+
self
102+
}
103+
104+
/// Define a closure that can setup plugin specific state.
105+
pub fn setup<F>(mut self, setup: F) -> Self
106+
where
107+
F: Fn(&AppHandle<R>) -> Result<()> + Send + Sync + 'static,
108+
{
109+
self.setup = Box::new(setup);
110+
self
111+
}
112+
113+
/// Callback invoked when the webview performs a navigation to a page.
114+
pub fn on_page_load<F>(mut self, on_page_load: F) -> Self
115+
where
116+
F: Fn(Window<R>, PageLoadPayload) + Send + Sync + 'static,
117+
{
118+
self.on_page_load = Box::new(on_page_load);
119+
self
120+
}
121+
122+
/// Callback invoked when the webview is created.
123+
pub fn on_webview_ready<F>(mut self, on_webview_ready: F) -> Self
124+
where
125+
F: Fn(Window<R>) + Send + Sync + 'static,
126+
{
127+
self.on_webview_ready = Box::new(on_webview_ready);
128+
self
129+
}
130+
131+
/// Callback invoked when the event loop receives a new event.
132+
pub fn on_event<F>(mut self, on_event: F) -> Self
133+
where
134+
F: Fn(&AppHandle<R>, &RunEvent) + Send + Sync + 'static,
135+
{
136+
self.on_event = Box::new(on_event);
137+
self
138+
}
139+
140+
/// Builds the [TauriPlugin].
141+
pub fn build(self) -> TauriPlugin<R> {
142+
TauriPlugin {
143+
name: self.name,
144+
invoke_handler: self.invoke_handler,
145+
setup: self.setup,
146+
js_init_script: self.js_init_script,
147+
on_page_load: self.on_page_load,
148+
on_webview_ready: self.on_webview_ready,
149+
on_event: self.on_event,
150+
}
151+
}
152+
}
153+
154+
/// Plugin struct that is returned by the [`PluginBuilder`]. Should only be constructed through the builder.
155+
pub struct TauriPlugin<R: Runtime> {
156+
name: &'static str,
157+
invoke_handler: Box<InvokeHandler<R>>,
158+
setup: Box<SetupHook<R>>,
159+
js_init_script: Option<String>,
160+
on_page_load: Box<OnPageLoad<R>>,
161+
on_webview_ready: Box<OnWebviewReady<R>>,
162+
on_event: Box<OnEvent<R>>,
163+
}
164+
165+
impl<R: Runtime> Plugin<R> for TauriPlugin<R> {
166+
fn name(&self) -> &'static str {
167+
self.name
168+
}
169+
170+
fn initialize(&mut self, app: &AppHandle<R>, _: JsonValue) -> Result<()> {
171+
(self.setup)(app)
172+
}
173+
174+
fn initialization_script(&self) -> Option<String> {
175+
self.js_init_script.clone()
176+
}
177+
178+
fn created(&mut self, window: Window<R>) {
179+
(self.on_webview_ready)(window)
180+
}
181+
182+
fn on_page_load(&mut self, window: Window<R>, payload: PageLoadPayload) {
183+
(self.on_page_load)(window, payload)
184+
}
185+
186+
fn on_event(&mut self, app: &AppHandle<R>, event: &RunEvent) {
187+
(self.on_event)(app, event)
188+
}
189+
190+
fn extend_api(&mut self, invoke: Invoke<R>) {
191+
(self.invoke_handler)(invoke)
192+
}
193+
}
194+
56195
/// Plugin collection type.
57196
#[default_runtime(crate::Wry, wry)]
58197
pub(crate) struct PluginStore<R: Runtime> {

0 commit comments

Comments
 (0)