mirror of
https://github.com/tauri-apps/tauri.git
synced 2024-09-22 13:48:13 +03:00
refactor(core): app hooks (#1332)
This commit is contained in:
parent
99dbc42cf1
commit
dd5a945b7e
@ -1,5 +1,5 @@
|
||||
use futures::future::BoxFuture;
|
||||
use serde::Serialize;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::Value as JsonValue;
|
||||
use tauri_api::{config::Config, private::AsTauriContext};
|
||||
|
||||
@ -23,7 +23,9 @@ pub use webview_manager::{WebviewDispatcher, WebviewManager};
|
||||
type InvokeHandler<A> = dyn Fn(WebviewManager<A>, String, JsonValue) -> BoxFuture<'static, crate::Result<InvokeResponse>>
|
||||
+ Send
|
||||
+ Sync;
|
||||
type Setup<A> = dyn Fn(WebviewManager<A>) -> BoxFuture<'static, ()> + Send + Sync;
|
||||
type ManagerHook<A> = dyn Fn(WebviewManager<A>) -> BoxFuture<'static, ()> + Send + Sync;
|
||||
type PageLoadHook<A> =
|
||||
dyn Fn(WebviewManager<A>, PageLoadPayload) -> BoxFuture<'static, ()> + Send + Sync;
|
||||
|
||||
/// `App` runtime information.
|
||||
pub struct Context {
|
||||
@ -63,12 +65,27 @@ impl<T: Serialize> From<T> for InvokeResponse {
|
||||
}
|
||||
}
|
||||
|
||||
/// The payload for the "page_load" hook.
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
pub struct PageLoadPayload {
|
||||
url: String,
|
||||
}
|
||||
|
||||
impl PageLoadPayload {
|
||||
/// The page URL.
|
||||
pub fn url(&self) -> &str {
|
||||
&self.url
|
||||
}
|
||||
}
|
||||
|
||||
/// The application runner.
|
||||
pub struct App<A: ApplicationExt> {
|
||||
/// The JS message handler.
|
||||
invoke_handler: Option<Box<InvokeHandler<A>>>,
|
||||
/// The setup callback, invoked when the webview is ready.
|
||||
setup: Option<Box<Setup<A>>>,
|
||||
/// The page load hook, invoked when the webview performs a navigation.
|
||||
on_page_load: Option<Box<PageLoadHook<A>>>,
|
||||
/// The setup hook, invoked when the webviews have been created.
|
||||
setup: Option<Box<ManagerHook<A>>>,
|
||||
/// The context the App was created with
|
||||
pub(crate) context: Context,
|
||||
pub(crate) dispatchers: Arc<Mutex<HashMap<String, WebviewDispatcher<A::Dispatcher>>>>,
|
||||
@ -118,10 +135,22 @@ impl<A: ApplicationExt + 'static> App<A> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Runs the setup callback if defined.
|
||||
pub(crate) async fn run_setup(&self, dispatcher: &WebviewManager<A>) {
|
||||
/// Runs the setup hook if defined.
|
||||
pub(crate) async fn run_setup(&self, dispatcher: WebviewManager<A>) {
|
||||
if let Some(ref setup) = self.setup {
|
||||
let fut = setup(dispatcher.clone());
|
||||
let fut = setup(dispatcher);
|
||||
fut.await;
|
||||
}
|
||||
}
|
||||
|
||||
/// Runs the on page load hook if defined.
|
||||
pub(crate) async fn run_on_page_load(
|
||||
&self,
|
||||
dispatcher: &WebviewManager<A>,
|
||||
payload: PageLoadPayload,
|
||||
) {
|
||||
if let Some(ref on_page_load) = self.on_page_load {
|
||||
let fut = on_page_load(dispatcher.clone(), payload);
|
||||
fut.await;
|
||||
}
|
||||
}
|
||||
@ -197,8 +226,10 @@ where
|
||||
{
|
||||
/// The JS message handler.
|
||||
invoke_handler: Option<Box<InvokeHandler<A>>>,
|
||||
/// The setup callback, invoked when the webview is ready.
|
||||
setup: Option<Box<Setup<A>>>,
|
||||
/// The setup hook.
|
||||
setup: Option<Box<ManagerHook<A>>>,
|
||||
/// Page load hook.
|
||||
on_page_load: Option<Box<PageLoadHook<A>>>,
|
||||
config: PhantomData<C>,
|
||||
/// The webview dispatchers.
|
||||
dispatchers: Arc<Mutex<HashMap<String, WebviewDispatcher<A::Dispatcher>>>>,
|
||||
@ -212,6 +243,7 @@ impl<A: ApplicationExt + 'static, C: AsTauriContext> AppBuilder<C, A> {
|
||||
Self {
|
||||
invoke_handler: None,
|
||||
setup: None,
|
||||
on_page_load: None,
|
||||
config: Default::default(),
|
||||
dispatchers: Default::default(),
|
||||
webviews: Default::default(),
|
||||
@ -232,7 +264,7 @@ impl<A: ApplicationExt + 'static, C: AsTauriContext> AppBuilder<C, A> {
|
||||
self
|
||||
}
|
||||
|
||||
/// Defines the setup callback.
|
||||
/// Defines the setup hook.
|
||||
pub fn setup<
|
||||
T: futures::Future<Output = ()> + Send + Sync + 'static,
|
||||
F: Fn(WebviewManager<A>) -> T + Send + Sync + 'static,
|
||||
@ -246,6 +278,20 @@ impl<A: ApplicationExt + 'static, C: AsTauriContext> AppBuilder<C, A> {
|
||||
self
|
||||
}
|
||||
|
||||
/// Defines the page load hook.
|
||||
pub fn on_page_load<
|
||||
T: futures::Future<Output = ()> + Send + Sync + 'static,
|
||||
F: Fn(WebviewManager<A>, PageLoadPayload) -> T + Send + Sync + 'static,
|
||||
>(
|
||||
mut self,
|
||||
on_page_load: F,
|
||||
) -> Self {
|
||||
self.on_page_load = Some(Box::new(move |webview_manager, payload| {
|
||||
Box::pin(on_page_load(webview_manager, payload))
|
||||
}));
|
||||
self
|
||||
}
|
||||
|
||||
/// Adds a plugin to the runtime.
|
||||
pub fn plugin(
|
||||
self,
|
||||
@ -283,6 +329,7 @@ impl<A: ApplicationExt + 'static, C: AsTauriContext> AppBuilder<C, A> {
|
||||
Ok(App {
|
||||
invoke_handler: self.invoke_handler,
|
||||
setup: self.setup,
|
||||
on_page_load: self.on_page_load,
|
||||
context,
|
||||
dispatchers: self.dispatchers,
|
||||
webviews: Some(self.webviews),
|
||||
@ -303,6 +350,7 @@ fn run<A: ApplicationExt + 'static>(mut application: App<A>) -> crate::Result<()
|
||||
|
||||
let application = Arc::new(application);
|
||||
let mut webview_app = A::new()?;
|
||||
let mut main_webview_manager = None;
|
||||
|
||||
for webview in webviews {
|
||||
let webview_label = webview.label.to_string();
|
||||
@ -311,6 +359,9 @@ fn run<A: ApplicationExt + 'static>(mut application: App<A>) -> crate::Result<()
|
||||
application.dispatchers.clone(),
|
||||
webview_label.to_string(),
|
||||
);
|
||||
if main_webview_manager.is_none() {
|
||||
main_webview_manager = Some(webview_manager.clone());
|
||||
}
|
||||
let (webview_builder, rpc_handler, custom_protocol) =
|
||||
crate::async_runtime::block_on(application.init_webview(webview))?;
|
||||
|
||||
@ -322,6 +373,10 @@ fn run<A: ApplicationExt + 'static>(mut application: App<A>) -> crate::Result<()
|
||||
));
|
||||
}
|
||||
|
||||
if let Some(main_webview_manager) = main_webview_manager {
|
||||
crate::async_runtime::block_on(application.run_setup(main_webview_manager));
|
||||
}
|
||||
|
||||
webview_app.run();
|
||||
|
||||
Ok(())
|
||||
|
@ -12,7 +12,7 @@ use crate::{
|
||||
|
||||
use super::{
|
||||
webview::{CustomProtocol, WebviewBuilderExtPrivate, WebviewRpcHandler},
|
||||
App, Context, RpcRequest, Webview, WebviewManager,
|
||||
App, Context, PageLoadPayload, RpcRequest, Webview, WebviewManager,
|
||||
};
|
||||
|
||||
use serde::Deserialize;
|
||||
@ -85,10 +85,10 @@ pub(super) fn initialization_script(
|
||||
{tauri_initialization_script}
|
||||
{event_initialization_script}
|
||||
if (window.rpc) {{
|
||||
window.__TAURI__.invoke("__initialized")
|
||||
window.__TAURI__.invoke("__initialized", {{ url: window.location.href }})
|
||||
}} else {{
|
||||
window.addEventListener('DOMContentLoaded', function () {{
|
||||
window.__TAURI__.invoke("__initialized")
|
||||
window.__TAURI__.invoke("__initialized", {{ url: window.location.href }})
|
||||
}})
|
||||
}}
|
||||
{plugin_initialization_script}
|
||||
@ -154,7 +154,6 @@ pub(super) fn build_webview<A: ApplicationExt + 'static>(
|
||||
plugin_initialization_script: &str,
|
||||
context: &Context,
|
||||
) -> crate::Result<BuiltWebview<A>> {
|
||||
// TODO let debug = cfg!(debug_assertions);
|
||||
let webview_url = match &webview.url {
|
||||
WindowUrl::App => content_url.to_string(),
|
||||
WindowUrl::Custom(url) => url.to_string(),
|
||||
@ -324,8 +323,11 @@ async fn on_message<A: ApplicationExt + 'static>(
|
||||
message: Message,
|
||||
) -> crate::Result<InvokeResponse> {
|
||||
if &command == "__initialized" {
|
||||
application.run_setup(&webview_manager).await;
|
||||
crate::plugin::ready(A::plugin_store(), &webview_manager).await;
|
||||
let payload: PageLoadPayload = serde_json::from_value(message.inner)?;
|
||||
application
|
||||
.run_on_page_load(&webview_manager, payload.clone())
|
||||
.await;
|
||||
crate::plugin::on_page_load(A::plugin_store(), &webview_manager, payload).await;
|
||||
Ok(().into())
|
||||
} else {
|
||||
let response = if let Some(module) = &message.tauri_module {
|
||||
|
@ -1,4 +1,6 @@
|
||||
use crate::{api::config::PluginConfig, async_runtime::Mutex, ApplicationExt, WebviewManager};
|
||||
use crate::{
|
||||
api::config::PluginConfig, async_runtime::Mutex, ApplicationExt, PageLoadPayload, WebviewManager,
|
||||
};
|
||||
|
||||
use futures::future::join_all;
|
||||
use serde_json::Value as JsonValue;
|
||||
@ -30,9 +32,9 @@ pub trait Plugin<A: ApplicationExt + 'static>: Send + Sync {
|
||||
#[allow(unused_variables)]
|
||||
async fn created(&mut self, webview_manager: WebviewManager<A>) {}
|
||||
|
||||
/// Callback invoked when the webview is ready.
|
||||
/// Callback invoked when the webview performs a navigation.
|
||||
#[allow(unused_variables)]
|
||||
async fn ready(&mut self, webview_manager: WebviewManager<A>) {}
|
||||
async fn on_page_load(&mut self, webview_manager: WebviewManager<A>, payload: PageLoadPayload) {}
|
||||
|
||||
/// Add invoke_handler API extension commands.
|
||||
#[allow(unused_variables)]
|
||||
@ -109,14 +111,15 @@ pub(crate) async fn created<A: ApplicationExt + 'static>(
|
||||
join_all(futures).await;
|
||||
}
|
||||
|
||||
pub(crate) async fn ready<A: ApplicationExt + 'static>(
|
||||
pub(crate) async fn on_page_load<A: ApplicationExt + 'static>(
|
||||
store: &PluginStore<A>,
|
||||
webview_manager: &crate::WebviewManager<A>,
|
||||
payload: PageLoadPayload,
|
||||
) {
|
||||
let mut plugins = store.lock().await;
|
||||
let mut futures = Vec::new();
|
||||
for plugin in plugins.iter_mut() {
|
||||
futures.push(plugin.ready(webview_manager.clone()));
|
||||
futures.push(plugin.on_page_load(webview_manager.clone(), payload.clone()));
|
||||
}
|
||||
join_all(futures).await;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user