mirror of
https://github.com/tauri-apps/tauri.git
synced 2024-11-28 12:27:16 +03:00
refactor(app): run setup and window creation when event loop is ready (#4914)
This commit is contained in:
parent
6119f4582e
commit
b4622ea4d3
@ -3,7 +3,6 @@
|
||||
"timeout": 3600000,
|
||||
"pkgManagers": {
|
||||
"rust": {
|
||||
"errorOnVersionRange": "^2.0.0-0",
|
||||
"version": true,
|
||||
"getPublishedVersion": "cargo search ${ pkgFile.pkg.package.name } --limit 1 | sed -nE \"s/^[^\\\"]*\\\"//; s/\\\".*//1p\"",
|
||||
"prepublish": [
|
||||
@ -78,7 +77,6 @@
|
||||
]
|
||||
},
|
||||
"javascript": {
|
||||
"errorOnVersionRange": "^2.0.0-0",
|
||||
"version": true,
|
||||
"getPublishedVersion": "npm view ${ pkgFile.pkg.name } version",
|
||||
"prepublish": [
|
||||
|
5
.changes/refactor-setup.md
Normal file
5
.changes/refactor-setup.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
"tauri": major
|
||||
---
|
||||
|
||||
**Breaking change:** The window creation and setup hook are now called when the event loop is ready.
|
@ -40,6 +40,7 @@ use tauri_utils::PackageInfo;
|
||||
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
fmt,
|
||||
path::{Path, PathBuf},
|
||||
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.
|
||||
#[default_runtime(crate::Wry, wry)]
|
||||
#[derive(Debug)]
|
||||
pub struct App<R: Runtime> {
|
||||
runtime: Option<R>,
|
||||
pending_windows: Option<Vec<PendingWindow<EventLoopMessage, R>>>,
|
||||
setup: Option<SetupHook<R>>,
|
||||
manager: WindowManager<R>,
|
||||
#[cfg(all(desktop, feature = "global-shortcut"))]
|
||||
global_shortcut_manager: R::GlobalShortcutManager,
|
||||
@ -537,6 +539,22 @@ pub struct App<R: Runtime> {
|
||||
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> ManagerBase<R> for App<R> {
|
||||
fn manager(&self) -> &WindowManager<R> {
|
||||
@ -544,7 +562,11 @@ impl<R: Runtime> ManagerBase<R> for App<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> {
|
||||
@ -775,6 +797,17 @@ impl<R: Runtime> App<R> {
|
||||
let app_handle = self.handle();
|
||||
let manager = self.manager.clone();
|
||||
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 => {
|
||||
on_event_loop_event(
|
||||
&app_handle,
|
||||
@ -1460,8 +1493,11 @@ impl<R: Runtime> Builder<R> {
|
||||
#[cfg(feature = "clipboard")]
|
||||
let clipboard_manager = runtime.clipboard_manager();
|
||||
|
||||
#[allow(unused_mut)]
|
||||
let mut app = App {
|
||||
runtime: Some(runtime),
|
||||
pending_windows: Some(self.pending_windows),
|
||||
setup: Some(self.setup),
|
||||
manager: manager.clone(),
|
||||
#[cfg(all(desktop, feature = "global-shortcut"))]
|
||||
global_shortcut_manager: global_shortcut_manager.clone(),
|
||||
@ -1551,26 +1587,6 @@ impl<R: Runtime> Builder<R> {
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
@ -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>(
|
||||
app_handle: &AppHandle<R>,
|
||||
event: RuntimeRunEvent<EventLoopMessage>,
|
||||
|
@ -13,10 +13,10 @@ use std::{borrow::Cow, sync::Arc};
|
||||
|
||||
#[cfg(shell_scope)]
|
||||
use crate::ShellScopeConfig;
|
||||
use crate::{Manager, Pattern};
|
||||
use crate::{Manager, Pattern, WindowBuilder};
|
||||
use tauri_utils::{
|
||||
assets::{AssetKey, Assets, CspHash},
|
||||
config::{CliConfig, Config, PatternKind, TauriConfig},
|
||||
config::{CliConfig, Config, PatternKind, TauriConfig, WindowUrl},
|
||||
};
|
||||
|
||||
pub struct NoopAsset {
|
||||
@ -46,7 +46,7 @@ pub fn mock_context<A: Assets>(assets: A) -> crate::Context<A> {
|
||||
package: Default::default(),
|
||||
tauri: TauriConfig {
|
||||
pattern: PatternKind::Brownfield,
|
||||
windows: vec![Default::default()],
|
||||
windows: Vec::new(),
|
||||
cli: Some(CliConfig {
|
||||
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> {
|
||||
crate::Builder::<MockRuntime>::new()
|
||||
let app = crate::Builder::<MockRuntime>::new()
|
||||
.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> {
|
||||
|
Loading…
Reference in New Issue
Block a user