|
5 | 5 | //! The Tauri plugin extension to expand Tauri functionality. |
6 | 6 |
|
7 | 7 | 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, |
10 | 10 | }; |
11 | 11 | use serde_json::Value as JsonValue; |
12 | 12 | use tauri_macros::default_runtime; |
@@ -53,6 +53,145 @@ pub trait Plugin<R: Runtime>: Send { |
53 | 53 | fn extend_api(&mut self, invoke: Invoke<R>) {} |
54 | 54 | } |
55 | 55 |
|
| 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 | + |
56 | 195 | /// Plugin collection type. |
57 | 196 | #[default_runtime(crate::Wry, wry)] |
58 | 197 | pub(crate) struct PluginStore<R: Runtime> { |
|
0 commit comments