mirror of https://github.com/tauri-apps/tauri
feat(tauri) add splashscreen API (#400)
* feat(tauri) add splashscreen API * fix(examples) quasar example building
This commit is contained in:
parent
a572fb3dc7
commit
3e1ce404f5
|
@ -18,6 +18,20 @@
|
||||||
* and also whitelist them based upon the developer's settings.
|
* and also whitelist them based upon the developer's settings.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// makes the window.external.invoke API available after window.location.href changes
|
||||||
|
if (navigator.platform != "Win64" && navigator.plaform != "Win32") {
|
||||||
|
window.external = this
|
||||||
|
if (navigator.platform == "MacIntel") {
|
||||||
|
invoke = function (x) {
|
||||||
|
webkit.messageHandlers.invoke.postMessage(x);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
invoke = function (x) {
|
||||||
|
window.webkit.messageHandlers.external.postMessage(x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function s4() {
|
function s4() {
|
||||||
return Math.floor((1 + Math.random()) * 0x10000)
|
return Math.floor((1 + Math.random()) * 0x10000)
|
||||||
.toString(16)
|
.toString(16)
|
||||||
|
|
|
@ -13,8 +13,8 @@ use std::io::BufRead;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
tauri::AppBuilder::new()
|
tauri::AppBuilder::new()
|
||||||
.setup(|_webview| {
|
.setup(|webview, _| {
|
||||||
let handle1 = _webview.handle();
|
let handle1 = webview.handle();
|
||||||
std::thread::spawn(move || {
|
std::thread::spawn(move || {
|
||||||
let resource_dir = tauri::api::platform::resource_dir().expect("failed to get resource dir");
|
let resource_dir = tauri::api::platform::resource_dir().expect("failed to get resource dir");
|
||||||
let node_package_path = resource_dir.join("resources/packaged-node.js");
|
let node_package_path = resource_dir.join("resources/packaged-node.js");
|
||||||
|
@ -35,7 +35,7 @@ fn main() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
let handle2 = _webview.handle();
|
let handle2 = webview.handle();
|
||||||
tauri::event::listen(String::from("hello"), move |msg| {
|
tauri::event::listen(String::from("hello"), move |msg| {
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
pub struct Reply {
|
pub struct Reply {
|
||||||
|
|
|
@ -6,7 +6,8 @@ mod runner;
|
||||||
|
|
||||||
pub struct App {
|
pub struct App {
|
||||||
invoke_handler: Option<Box<dyn FnMut(&mut WebView<'_, ()>, &str)>>,
|
invoke_handler: Option<Box<dyn FnMut(&mut WebView<'_, ()>, &str)>>,
|
||||||
setup: Option<Box<dyn FnMut(&mut WebView<'_, ()>)>>,
|
setup: Option<Box<dyn FnMut(&mut WebView<'_, ()>, String)>>,
|
||||||
|
splashscreen_html: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl App {
|
impl App {
|
||||||
|
@ -23,19 +24,24 @@ impl App {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn run_setup(&mut self, webview: &mut WebView<'_, ()>) {
|
pub(crate) fn run_setup(&mut self, webview: &mut WebView<'_, ()>, source: String) {
|
||||||
match self.setup {
|
match self.setup {
|
||||||
Some(ref mut setup) => {
|
Some(ref mut setup) => {
|
||||||
setup(webview);
|
setup(webview, source);
|
||||||
}
|
}
|
||||||
None => {}
|
None => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn splashscreen_html(&self) -> Option<&String> {
|
||||||
|
self.splashscreen_html.as_ref()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct AppBuilder {
|
pub struct AppBuilder {
|
||||||
invoke_handler: Option<Box<dyn FnMut(&mut WebView<'_, ()>, &str)>>,
|
invoke_handler: Option<Box<dyn FnMut(&mut WebView<'_, ()>, &str)>>,
|
||||||
setup: Option<Box<dyn FnMut(&mut WebView<'_, ()>)>>,
|
setup: Option<Box<dyn FnMut(&mut WebView<'_, ()>, String)>>,
|
||||||
|
splashscreen_html: Option<String>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AppBuilder {
|
impl AppBuilder {
|
||||||
|
@ -43,6 +49,7 @@ impl AppBuilder {
|
||||||
Self {
|
Self {
|
||||||
invoke_handler: None,
|
invoke_handler: None,
|
||||||
setup: None,
|
setup: None,
|
||||||
|
splashscreen_html: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,15 +61,21 @@ impl AppBuilder {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setup<F: FnMut(&mut WebView<'_, ()>) + 'static>(mut self, setup: F) -> Self {
|
pub fn setup<F: FnMut(&mut WebView<'_, ()>, String) + 'static>(mut self, setup: F) -> Self {
|
||||||
self.setup = Some(Box::new(setup));
|
self.setup = Some(Box::new(setup));
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn splashscreen_html(mut self, html: &str) -> Self {
|
||||||
|
self.splashscreen_html = Some(html.to_string());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
pub fn build(self) -> App {
|
pub fn build(self) -> App {
|
||||||
App {
|
App {
|
||||||
invoke_handler: self.invoke_handler,
|
invoke_handler: self.invoke_handler,
|
||||||
setup: self.setup,
|
setup: self.setup,
|
||||||
|
splashscreen_html: self.splashscreen_html,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,12 +35,12 @@ pub(crate) fn run(application: &mut App) -> crate::Result<()> {
|
||||||
let config = get()?;
|
let config = get()?;
|
||||||
|
|
||||||
// setup the content using the config struct depending on the compile target
|
// setup the content using the config struct depending on the compile target
|
||||||
let content = setup_content(config.clone())?;
|
let main_content = setup_content(config.clone())?;
|
||||||
|
|
||||||
// setup the server url for the embedded-server
|
// setup the server url for the embedded-server
|
||||||
#[cfg(feature = "embedded-server")]
|
#[cfg(feature = "embedded-server")]
|
||||||
let server_url = {
|
let server_url = {
|
||||||
if let Content::Url(ref url) = &content {
|
if let Content::Url(ref url) = &main_content {
|
||||||
String::from(url)
|
String::from(url)
|
||||||
} else {
|
} else {
|
||||||
String::from("")
|
String::from("")
|
||||||
|
@ -48,8 +48,16 @@ pub(crate) fn run(application: &mut App) -> crate::Result<()> {
|
||||||
};
|
};
|
||||||
|
|
||||||
// build the webview
|
// build the webview
|
||||||
let mut webview = build_webview(application, config, content)?;
|
let webview = build_webview(
|
||||||
webview.set_color((255, 255, 255));
|
application,
|
||||||
|
config,
|
||||||
|
main_content,
|
||||||
|
if application.splashscreen_html().is_some() {
|
||||||
|
Some(Content::Html(application.splashscreen_html().expect("failed to get splashscreen_html").to_string()))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
|
||||||
// on dev-server grab a handler and execute the tauri.js API entry point.
|
// on dev-server grab a handler and execute the tauri.js API entry point.
|
||||||
#[cfg(feature = "dev-server")]
|
#[cfg(feature = "dev-server")]
|
||||||
|
@ -172,7 +180,12 @@ fn build_webview(
|
||||||
application: &mut App,
|
application: &mut App,
|
||||||
config: Config,
|
config: Config,
|
||||||
content: Content<String>,
|
content: Content<String>,
|
||||||
|
splashscreen_content: Option<Content<String>>
|
||||||
) -> crate::Result<WebView<'_, ()>> {
|
) -> crate::Result<WebView<'_, ()>> {
|
||||||
|
let content_clone = match content {
|
||||||
|
Content::Html(ref html) => Content::Html(html.clone()),
|
||||||
|
Content::Url(ref url) => Content::Url(url.clone()),
|
||||||
|
};
|
||||||
let debug = cfg!(debug_assertions);
|
let debug = cfg!(debug_assertions);
|
||||||
// get properties from config struct
|
// get properties from config struct
|
||||||
let width = config.tauri.window.width;
|
let width = config.tauri.window.width;
|
||||||
|
@ -180,8 +193,10 @@ fn build_webview(
|
||||||
let resizable = config.tauri.window.resizable;
|
let resizable = config.tauri.window.resizable;
|
||||||
let title = config.tauri.window.title.into_boxed_str();
|
let title = config.tauri.window.title.into_boxed_str();
|
||||||
|
|
||||||
Ok(
|
let has_splashscreen = splashscreen_content.is_some();
|
||||||
builder()
|
let mut initialized_splashscreen = false;
|
||||||
|
|
||||||
|
let webview = builder()
|
||||||
.title(Box::leak(title))
|
.title(Box::leak(title))
|
||||||
.size(width, height)
|
.size(width, height)
|
||||||
.resizable(resizable)
|
.resizable(resizable)
|
||||||
|
@ -189,8 +204,20 @@ fn build_webview(
|
||||||
.user_data(())
|
.user_data(())
|
||||||
.invoke_handler(move |webview, arg| {
|
.invoke_handler(move |webview, arg| {
|
||||||
if arg == r#"{"cmd":"__initialized"}"# {
|
if arg == r#"{"cmd":"__initialized"}"# {
|
||||||
application.run_setup(webview);
|
let source = if has_splashscreen && !initialized_splashscreen {
|
||||||
|
initialized_splashscreen = true;
|
||||||
|
"splashscreen"
|
||||||
|
} else {
|
||||||
|
"window-1"
|
||||||
|
};
|
||||||
|
application.run_setup(webview, source.to_string());
|
||||||
webview.eval(JS_STRING)?;
|
webview.eval(JS_STRING)?;
|
||||||
|
} else if arg == r#"{"cmd":"closeSplashscreen"}"# {
|
||||||
|
let content_href = match content_clone {
|
||||||
|
Content::Html(ref html) => html,
|
||||||
|
Content::Url(ref url) => url,
|
||||||
|
};
|
||||||
|
webview.eval(&format!("window.location.href = `{}`", content_href))?;
|
||||||
} else if let Ok(b) = crate::endpoints::handle(webview, arg) {
|
} else if let Ok(b) = crate::endpoints::handle(webview, arg) {
|
||||||
if !b {
|
if !b {
|
||||||
application.run_invoke_handler(webview, arg);
|
application.run_invoke_handler(webview, arg);
|
||||||
|
@ -199,9 +226,21 @@ fn build_webview(
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
.content(content)
|
.content(if splashscreen_content.is_some() {
|
||||||
.build()?,
|
splashscreen_content.expect("failed to get splashscreen content")
|
||||||
)
|
} else {
|
||||||
|
content
|
||||||
|
})
|
||||||
|
.build()?;
|
||||||
|
|
||||||
|
if has_splashscreen {
|
||||||
|
// trigger the init hook for the splashscreen since we're not injecting the tauri.js entry point
|
||||||
|
webview.handle().dispatch(|webview| {
|
||||||
|
webview.eval(r#"window.external.invoke(JSON.stringify({ cmd: "__initialized" }))"#)
|
||||||
|
}).expect("failed to initialize splashscreen");
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(webview)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
@ -36,7 +36,7 @@ use threadpool::ThreadPool;
|
||||||
use error_chain::error_chain;
|
use error_chain::error_chain;
|
||||||
|
|
||||||
pub use app::*;
|
pub use app::*;
|
||||||
use web_view::WebView;
|
use web_view::{WebView, Handle};
|
||||||
|
|
||||||
pub use tauri_api as api;
|
pub use tauri_api as api;
|
||||||
|
|
||||||
|
@ -106,6 +106,14 @@ pub fn call<T: 'static>(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn close_splashscreen<T: 'static>(webview_handle: &Handle<T>) -> crate::Result<()> {
|
||||||
|
webview_handle.dispatch(|webview| {
|
||||||
|
// send a signal to the runner so it knows that it should redirect to the main app content
|
||||||
|
webview.eval(r#"window.external.invoke(JSON.stringify({ cmd: "closeSplashscreen" }))"#)
|
||||||
|
})?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use proptest::prelude::*;
|
use proptest::prelude::*;
|
||||||
|
|
Loading…
Reference in New Issue