Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(core): implement on_page_load event using wry hook #8116

Merged
merged 4 commits into from
Oct 27, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changes/on-page-load-hook.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"tauri-runtime": patch:feat
"tauri-runtime-wry": patch:feat
---

Added `on_page_load` hook for `PendingWindow`.
6 changes: 6 additions & 0 deletions .changes/refactor-on-page-load.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"tauri": patch:breaking
---

Added `WindowBuilder::on_page_load` and refactored the `Builder::on_page_load` handler to take references.
The page load hook is now triggered for load started and finished events, to determine what triggered it see `PageLoadPayload::event`.
15 changes: 15 additions & 0 deletions core/tauri-runtime-wry/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2725,6 +2725,21 @@ fn create_webview<T: UserEvent, F: Fn(RawWindow) + Send + 'static>(
.unwrap_or(true)
});
}

if let Some(page_load_handler) = pending.on_page_load_handler {
webview_builder = webview_builder.with_on_page_load_handler(move |event, url| {
let _ = Url::parse(&url).map(|url| {
page_load_handler(
url,
match event {
wry::webview::PageLoadEvent::Started => tauri_runtime::window::PageLoadEvent::Started,
wry::webview::PageLoadEvent::Finished => tauri_runtime::window::PageLoadEvent::Finished,
},
)
});
});
}

if let Some(user_agent) = webview_attributes.user_agent {
webview_builder = webview_builder.with_user_agent(&user_agent);
}
Expand Down
23 changes: 19 additions & 4 deletions core/tauri-runtime/src/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,17 @@ type WebResourceRequestHandler =

type NavigationHandler = dyn Fn(&Url) -> bool + Send;

type OnPageLoadHandler = dyn Fn(Url, PageLoadEvent) + Send;

/// Kind of event for the page load handler.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum PageLoadEvent {
/// Page started to load.
Started,
/// Page finished loading.
Finished,
}

/// UI scaling utilities.
pub mod dpi;

Expand Down Expand Up @@ -238,6 +249,8 @@ pub struct PendingWindow<T: UserEvent, R: Runtime<T>> {
Option<Box<dyn Fn(CreationContext<'_, '_>) -> Result<(), jni::errors::Error> + Send>>,

pub web_resource_request_handler: Option<Box<WebResourceRequestHandler>>,

pub on_page_load_handler: Option<Box<OnPageLoadHandler>>,
}

pub fn is_label_valid(label: &str) -> bool {
Expand Down Expand Up @@ -270,11 +283,12 @@ impl<T: UserEvent, R: Runtime<T>> PendingWindow<T, R> {
uri_scheme_protocols: Default::default(),
label,
ipc_handler: None,
navigation_handler: Default::default(),
navigation_handler: None,
url: "tauri://localhost".to_string(),
#[cfg(target_os = "android")]
on_webview_created: None,
web_resource_request_handler: Default::default(),
web_resource_request_handler: None,
on_page_load_handler: None,
})
}
}
Expand All @@ -298,11 +312,12 @@ impl<T: UserEvent, R: Runtime<T>> PendingWindow<T, R> {
uri_scheme_protocols: Default::default(),
label,
ipc_handler: None,
navigation_handler: Default::default(),
navigation_handler: None,
url: "tauri://localhost".to_string(),
#[cfg(target_os = "android")]
on_webview_created: None,
web_resource_request_handler: Default::default(),
web_resource_request_handler: None,
on_page_load_handler: None,
})
}
}
Expand Down
15 changes: 1 addition & 14 deletions core/tauri/scripts/init.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,8 @@
__RAW_core_script__

__RAW_event_initialization_script__
;(function () {
__RAW_bundle_script__
})()

if (window.ipc) {
window.__TAURI_INTERNALS__.invoke('__initialized', {
url: window.location.href
})
} else {
window.addEventListener('DOMContentLoaded', function () {
window.__TAURI_INTERNALS__.invoke('__initialized', {
url: window.location.href
})
})
}
__RAW_bundle_script__

__RAW_plugin_initialization_script__
})()
25 changes: 6 additions & 19 deletions core/tauri/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ use crate::{
sealed::{ManagerBase, RuntimeOrDispatch},
utils::config::Config,
utils::{assets::Assets, Env},
window::PageLoadPayload,
Context, DeviceEventFilter, EventLoopMessage, Icon, Manager, Monitor, Runtime, Scopes,
StateManager, Theme, Window,
};
Expand All @@ -30,7 +31,6 @@ use crate::tray::{TrayIcon, TrayIconBuilder, TrayIconEvent, TrayIconId};
#[cfg(desktop)]
use crate::window::WindowMenu;
use raw_window_handle::HasRawDisplayHandle;
use serde::Deserialize;
use serialize_to_javascript::{default_template, DefaultTemplate, Template};
use tauri_macros::default_runtime;
#[cfg(desktop)]
Expand Down Expand Up @@ -68,20 +68,7 @@ pub(crate) type GlobalWindowEventListener<R> = Box<dyn Fn(GlobalWindowEvent<R>)
pub type SetupHook<R> =
Box<dyn FnOnce(&mut App<R>) -> Result<(), Box<dyn std::error::Error>> + Send>;
/// A closure that is run once every time a window is created and loaded.
pub type OnPageLoad<R> = dyn Fn(Window<R>, PageLoadPayload) + Send + Sync + 'static;

/// The payload for the [`OnPageLoad`] hook.
#[derive(Debug, Clone, Deserialize)]
pub struct PageLoadPayload {
url: String,
}

impl PageLoadPayload {
/// The page URL.
pub fn url(&self) -> &str {
&self.url
}
}
pub type OnPageLoad<R> = dyn Fn(&Window<R>, &PageLoadPayload<'_>) + Send + Sync + 'static;

/// Api exposed on the `ExitRequested` event.
#[derive(Debug)]
Expand Down Expand Up @@ -982,7 +969,7 @@ pub struct Builder<R: Runtime> {
setup: SetupHook<R>,

/// Page load hook.
on_page_load: Box<OnPageLoad<R>>,
on_page_load: Option<Arc<OnPageLoad<R>>>,

/// windows to create when starting up.
pending_windows: Vec<PendingWindow<EventLoopMessage, R>>,
Expand Down Expand Up @@ -1040,7 +1027,7 @@ impl<R: Runtime> Builder<R> {
.render_default(&Default::default())
.unwrap()
.into_string(),
on_page_load: Box::new(|_, _| ()),
on_page_load: None,
pending_windows: Default::default(),
plugins: PluginStore::default(),
uri_scheme_protocols: Default::default(),
Expand Down Expand Up @@ -1130,9 +1117,9 @@ impl<R: Runtime> Builder<R> {
#[must_use]
pub fn on_page_load<F>(mut self, on_page_load: F) -> Self
where
F: Fn(Window<R>, PageLoadPayload) + Send + Sync + 'static,
F: Fn(&Window<R>, &PageLoadPayload<'_>) + Send + Sync + 'static,
{
self.on_page_load = Box::new(on_page_load);
self.on_page_load.replace(Arc::new(on_page_load));
self
}

Expand Down
49 changes: 31 additions & 18 deletions core/tauri/src/manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,8 @@ use tauri_utils::{
html::{SCRIPT_NONCE_TOKEN, STYLE_NONCE_TOKEN},
};

use crate::event::EmitArgs;
use crate::{
app::{
AppHandle, GlobalWindowEvent, GlobalWindowEventListener, OnPageLoad, PageLoadPayload,
UriSchemeResponder,
},
app::{AppHandle, GlobalWindowEvent, GlobalWindowEventListener, OnPageLoad, UriSchemeResponder},
event::{assert_event_name_is_valid, Event, EventId, Listeners},
ipc::{Invoke, InvokeHandler, InvokeResponder},
pattern::PatternJavascript,
Expand All @@ -52,6 +48,7 @@ use crate::{
Context, EventLoopMessage, Icon, Manager, Pattern, Runtime, Scopes, StateManager, Window,
WindowEvent,
};
use crate::{event::EmitArgs, window::PageLoadPayload};

#[cfg(desktop)]
use crate::app::GlobalMenuEventListener;
Expand Down Expand Up @@ -232,7 +229,7 @@ pub struct InnerWindowManager<R: Runtime> {
invoke_handler: Box<InvokeHandler<R>>,

/// The page load hook, invoked when the webview performs a navigation.
on_page_load: Box<OnPageLoad<R>>,
on_page_load: Option<Arc<OnPageLoad<R>>>,

config: Arc<Config>,
assets: Arc<dyn Assets>,
Expand Down Expand Up @@ -339,7 +336,7 @@ impl<R: Runtime> WindowManager<R> {
#[allow(unused_mut)] mut context: Context<impl Assets>,
plugins: PluginStore<R>,
invoke_handler: Box<InvokeHandler<R>>,
on_page_load: Box<OnPageLoad<R>>,
on_page_load: Option<Arc<OnPageLoad<R>>>,
uri_scheme_protocols: HashMap<String, Arc<UriSchemeProtocol<R>>>,
state: StateManager,
window_event_listeners: Vec<GlobalWindowEventListener<R>>,
Expand Down Expand Up @@ -685,6 +682,32 @@ impl<R: Runtime> WindowManager<R> {
registered_scheme_protocols.push("ipc".into());
}

let label = pending.label.clone();
let manager = self.clone();
let on_page_load_handler = pending.on_page_load_handler.take();
pending
.on_page_load_handler
.replace(Box::new(move |url, event| {
let payload = PageLoadPayload { url: &url, event };

if let Some(w) = manager.get_window(&label) {
if let Some(on_page_load) = &manager.inner.on_page_load {
on_page_load(&w, &payload);
}

manager
.inner
.plugins
.lock()
.unwrap()
.on_page_load(&w, &payload);
}

if let Some(handler) = &on_page_load_handler {
handler(url, event);
}
}));

#[cfg(feature = "protocol-asset")]
if !registered_scheme_protocols.contains(&"asset".into()) {
let asset_scope = self.state().get::<crate::Scopes>().asset_protocol.clone();
Expand Down Expand Up @@ -869,16 +892,6 @@ impl<R: Runtime> WindowManager<R> {
(self.inner.invoke_handler)(invoke)
}

pub fn run_on_page_load(&self, window: Window<R>, payload: PageLoadPayload) {
(self.inner.on_page_load)(window.clone(), payload.clone());
self
.inner
.plugins
.lock()
.expect("poisoned plugin store")
.on_page_load(window, payload);
}

pub fn extend_api(&self, plugin: &str, invoke: Invoke<R>) -> bool {
self
.inner
Expand Down Expand Up @@ -1376,7 +1389,7 @@ mod test {
context,
PluginStore::default(),
Box::new(|_| false),
Box::new(|_, _| ()),
None,
Default::default(),
StateManager::new(),
Default::default(),
Expand Down
17 changes: 9 additions & 8 deletions core/tauri/src/plugin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@
//! The Tauri plugin extension to expand Tauri functionality.

use crate::{
app::{PageLoadPayload, UriSchemeResponder},
app::UriSchemeResponder,
error::Error,
ipc::{Invoke, InvokeHandler},
manager::UriSchemeProtocol,
utils::config::PluginConfig,
window::PageLoadPayload,
AppHandle, RunEvent, Runtime, Window,
};
use serde::de::DeserializeOwned;
Expand Down Expand Up @@ -62,7 +63,7 @@ pub trait Plugin<R: Runtime>: Send {

/// Callback invoked when the webview performs a navigation to a page.
#[allow(unused_variables)]
fn on_page_load(&mut self, window: Window<R>, payload: PageLoadPayload) {}
fn on_page_load(&mut self, window: &Window<R>, payload: &PageLoadPayload<'_>) {}

/// Callback invoked when the event loop receives a new event.
#[allow(unused_variables)]
Expand All @@ -80,7 +81,7 @@ type SetupHook<R, C> =
type OnWebviewReady<R> = dyn FnMut(Window<R>) + Send;
type OnEvent<R> = dyn FnMut(&AppHandle<R>, &RunEvent) + Send;
type OnNavigation<R> = dyn Fn(&Window<R>, &Url) -> bool + Send;
type OnPageLoad<R> = dyn FnMut(Window<R>, PageLoadPayload) + Send;
type OnPageLoad<R> = dyn FnMut(&Window<R>, &PageLoadPayload<'_>) + Send;
type OnDrop<R> = dyn FnOnce(AppHandle<R>) + Send;

/// A handle to a plugin.
Expand Down Expand Up @@ -368,15 +369,15 @@ impl<R: Runtime, C: DeserializeOwned> Builder<R, C> {
/// fn init<R: Runtime>() -> TauriPlugin<R> {
/// Builder::new("example")
/// .on_page_load(|window, payload| {
/// println!("Loaded URL {} in window {}", payload.url(), window.label());
/// println!("{:?} URL {} in window {}", payload.event(), payload.url(), window.label());
/// })
/// .build()
/// }
/// ```
#[must_use]
pub fn on_page_load<F>(mut self, on_page_load: F) -> Self
where
F: FnMut(Window<R>, PageLoadPayload) + Send + 'static,
F: FnMut(&Window<R>, &PageLoadPayload<'_>) + Send + 'static,
{
self.on_page_load = Box::new(on_page_load);
self
Expand Down Expand Up @@ -652,7 +653,7 @@ impl<R: Runtime, C: DeserializeOwned> Plugin<R> for TauriPlugin<R, C> {
(self.on_navigation)(window, url)
}

fn on_page_load(&mut self, window: Window<R>, payload: PageLoadPayload) {
fn on_page_load(&mut self, window: &Window<R>, payload: &PageLoadPayload<'_>) {
(self.on_page_load)(window, payload)
}

Expand Down Expand Up @@ -750,11 +751,11 @@ impl<R: Runtime> PluginStore<R> {
}

/// Runs the on_page_load hook for all plugins in the store.
pub(crate) fn on_page_load(&mut self, window: Window<R>, payload: PageLoadPayload) {
pub(crate) fn on_page_load(&mut self, window: &Window<R>, payload: &PageLoadPayload<'_>) {
self
.store
.iter_mut()
.for_each(|plugin| plugin.on_page_load(window.clone(), payload.clone()))
.for_each(|plugin| plugin.on_page_load(window, payload))
}

/// Runs the on_event hook for all plugins in the store.
Expand Down
Loading
Loading