refactor(app): run setup and window creation when event loop is ready (#4914)

This commit is contained in:
Lucas Fernandes Nogueira 2022-08-11 10:30:55 -03:00 committed by GitHub
parent 6119f4582e
commit b4622ea4d3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 86 additions and 29 deletions

View File

@ -3,7 +3,6 @@
"timeout": 3600000, "timeout": 3600000,
"pkgManagers": { "pkgManagers": {
"rust": { "rust": {
"errorOnVersionRange": "^2.0.0-0",
"version": true, "version": true,
"getPublishedVersion": "cargo search ${ pkgFile.pkg.package.name } --limit 1 | sed -nE \"s/^[^\\\"]*\\\"//; s/\\\".*//1p\"", "getPublishedVersion": "cargo search ${ pkgFile.pkg.package.name } --limit 1 | sed -nE \"s/^[^\\\"]*\\\"//; s/\\\".*//1p\"",
"prepublish": [ "prepublish": [
@ -78,7 +77,6 @@
] ]
}, },
"javascript": { "javascript": {
"errorOnVersionRange": "^2.0.0-0",
"version": true, "version": true,
"getPublishedVersion": "npm view ${ pkgFile.pkg.name } version", "getPublishedVersion": "npm view ${ pkgFile.pkg.name } version",
"prepublish": [ "prepublish": [

View File

@ -0,0 +1,5 @@
---
"tauri": major
---
**Breaking change:** The window creation and setup hook are now called when the event loop is ready.

View File

@ -40,6 +40,7 @@ use tauri_utils::PackageInfo;
use std::{ use std::{
collections::HashMap, collections::HashMap,
fmt,
path::{Path, PathBuf}, path::{Path, PathBuf},
sync::{mpsc::Sender, Arc, Weak}, sync::{mpsc::Sender, Arc, Weak},
}; };
@ -526,9 +527,10 @@ impl<R: Runtime> ManagerBase<R> for AppHandle<R> {
/// ///
/// This type implements [`Manager`] which allows for manipulation of global application items. /// This type implements [`Manager`] which allows for manipulation of global application items.
#[default_runtime(crate::Wry, wry)] #[default_runtime(crate::Wry, wry)]
#[derive(Debug)]
pub struct App<R: Runtime> { pub struct App<R: Runtime> {
runtime: Option<R>, runtime: Option<R>,
pending_windows: Option<Vec<PendingWindow<EventLoopMessage, R>>>,
setup: Option<SetupHook<R>>,
manager: WindowManager<R>, manager: WindowManager<R>,
#[cfg(all(desktop, feature = "global-shortcut"))] #[cfg(all(desktop, feature = "global-shortcut"))]
global_shortcut_manager: R::GlobalShortcutManager, global_shortcut_manager: R::GlobalShortcutManager,
@ -537,6 +539,22 @@ pub struct App<R: Runtime> {
handle: AppHandle<R>, handle: AppHandle<R>,
} }
impl<R: Runtime> fmt::Debug for App<R> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut d = f.debug_struct("App");
d.field("runtime", &self.runtime)
.field("manager", &self.manager)
.field("handle", &self.handle);
#[cfg(all(desktop, feature = "global-shortcut"))]
d.field("global_shortcut_manager", &self.global_shortcut_manager);
#[cfg(feature = "clipboard")]
d.field("clipboard_manager", &self.clipboard_manager);
d.finish()
}
}
impl<R: Runtime> Manager<R> for App<R> {} impl<R: Runtime> Manager<R> for App<R> {}
impl<R: Runtime> ManagerBase<R> for App<R> { impl<R: Runtime> ManagerBase<R> for App<R> {
fn manager(&self) -> &WindowManager<R> { fn manager(&self) -> &WindowManager<R> {
@ -544,7 +562,11 @@ impl<R: Runtime> ManagerBase<R> for App<R> {
} }
fn runtime(&self) -> RuntimeOrDispatch<'_, R> { fn runtime(&self) -> RuntimeOrDispatch<'_, R> {
RuntimeOrDispatch::Runtime(self.runtime.as_ref().unwrap()) if let Some(runtime) = self.runtime.as_ref() {
RuntimeOrDispatch::Runtime(runtime)
} else {
self.handle.runtime()
}
} }
fn managed_app_handle(&self) -> AppHandle<R> { fn managed_app_handle(&self) -> AppHandle<R> {
@ -775,6 +797,17 @@ impl<R: Runtime> App<R> {
let app_handle = self.handle(); let app_handle = self.handle();
let manager = self.manager.clone(); let manager = self.manager.clone();
self.runtime.take().unwrap().run(move |event| match event { self.runtime.take().unwrap().run(move |event| match event {
RuntimeRunEvent::Ready => {
if let Err(e) = setup(&mut self) {
panic!("Failed to setup app: {}", e);
}
on_event_loop_event(
&app_handle,
RuntimeRunEvent::Ready,
&manager,
Some(&mut callback),
);
}
RuntimeRunEvent::Exit => { RuntimeRunEvent::Exit => {
on_event_loop_event( on_event_loop_event(
&app_handle, &app_handle,
@ -1460,8 +1493,11 @@ impl<R: Runtime> Builder<R> {
#[cfg(feature = "clipboard")] #[cfg(feature = "clipboard")]
let clipboard_manager = runtime.clipboard_manager(); let clipboard_manager = runtime.clipboard_manager();
#[allow(unused_mut)]
let mut app = App { let mut app = App {
runtime: Some(runtime), runtime: Some(runtime),
pending_windows: Some(self.pending_windows),
setup: Some(self.setup),
manager: manager.clone(), manager: manager.clone(),
#[cfg(all(desktop, feature = "global-shortcut"))] #[cfg(all(desktop, feature = "global-shortcut"))]
global_shortcut_manager: global_shortcut_manager.clone(), global_shortcut_manager: global_shortcut_manager.clone(),
@ -1551,26 +1587,6 @@ impl<R: Runtime> Builder<R> {
app.manager.initialize_plugins(&app.handle())?; app.manager.initialize_plugins(&app.handle())?;
let window_labels = self
.pending_windows
.iter()
.map(|p| p.label.clone())
.collect::<Vec<_>>();
for pending in self.pending_windows {
let pending =
app
.manager
.prepare_window(app.handle.clone(), pending, &window_labels, None)?;
let detached = app.runtime.as_ref().unwrap().create_window(pending)?;
let _window = app.manager.attach_window(app.handle(), detached);
}
(self.setup)(&mut app).map_err(|e| crate::Error::Setup(e.into()))?;
#[cfg(updater)]
app.run_updater();
Ok(app) Ok(app)
} }
@ -1593,6 +1609,38 @@ unsafe impl HasRawDisplayHandle for App {
} }
} }
fn setup<R: Runtime>(app: &mut App<R>) -> crate::Result<()> {
let pending_windows = app.pending_windows.take();
if let Some(pending_windows) = pending_windows {
let window_labels = pending_windows
.iter()
.map(|p| p.label.clone())
.collect::<Vec<_>>();
for pending in pending_windows {
let pending =
app
.manager
.prepare_window(app.handle.clone(), pending, &window_labels, None)?;
let detached = if let RuntimeOrDispatch::RuntimeHandle(runtime) = app.handle().runtime() {
runtime.create_window(pending)?
} else {
// the AppHandle's runtime is always RuntimeOrDispatch::RuntimeHandle
unreachable!()
};
let _window = app.manager.attach_window(app.handle(), detached);
}
}
if let Some(setup) = app.setup.take() {
(setup)(app).map_err(|e| crate::Error::Setup(e.into()))?;
}
#[cfg(updater)]
app.run_updater();
Ok(())
}
fn on_event_loop_event<R: Runtime, F: FnMut(&AppHandle<R>, RunEvent) + 'static>( fn on_event_loop_event<R: Runtime, F: FnMut(&AppHandle<R>, RunEvent) + 'static>(
app_handle: &AppHandle<R>, app_handle: &AppHandle<R>,
event: RuntimeRunEvent<EventLoopMessage>, event: RuntimeRunEvent<EventLoopMessage>,

View File

@ -13,10 +13,10 @@ use std::{borrow::Cow, sync::Arc};
#[cfg(shell_scope)] #[cfg(shell_scope)]
use crate::ShellScopeConfig; use crate::ShellScopeConfig;
use crate::{Manager, Pattern}; use crate::{Manager, Pattern, WindowBuilder};
use tauri_utils::{ use tauri_utils::{
assets::{AssetKey, Assets, CspHash}, assets::{AssetKey, Assets, CspHash},
config::{CliConfig, Config, PatternKind, TauriConfig}, config::{CliConfig, Config, PatternKind, TauriConfig, WindowUrl},
}; };
pub struct NoopAsset { pub struct NoopAsset {
@ -46,7 +46,7 @@ pub fn mock_context<A: Assets>(assets: A) -> crate::Context<A> {
package: Default::default(), package: Default::default(),
tauri: TauriConfig { tauri: TauriConfig {
pattern: PatternKind::Brownfield, pattern: PatternKind::Brownfield,
windows: vec![Default::default()], windows: Vec::new(),
cli: Some(CliConfig { cli: Some(CliConfig {
description: None, description: None,
long_description: None, long_description: None,
@ -86,9 +86,15 @@ pub fn mock_context<A: Assets>(assets: A) -> crate::Context<A> {
} }
pub fn mock_app() -> crate::App<MockRuntime> { pub fn mock_app() -> crate::App<MockRuntime> {
crate::Builder::<MockRuntime>::new() let app = crate::Builder::<MockRuntime>::new()
.build(mock_context(noop_assets())) .build(mock_context(noop_assets()))
.unwrap() .unwrap();
WindowBuilder::new(&app, "main", WindowUrl::App("index.html".into()))
.build()
.unwrap();
app
} }
pub(crate) fn mock_invoke_context() -> crate::endpoints::InvokeContext<MockRuntime> { pub(crate) fn mock_invoke_context() -> crate::endpoints::InvokeContext<MockRuntime> {