fix(core): immediately listen to window-created, closes #3297 (#3298)

This commit is contained in:
Lucas Fernandes Nogueira 2022-02-04 23:39:23 -03:00 committed by GitHub
parent 2bade5ecaa
commit 878b8b9a1f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 87 additions and 65 deletions

View File

@ -0,0 +1,5 @@
---
"tauri": patch
---
Immediately listen to `tauri://window-created` event to catch it before the application triggers it.

View File

@ -150,18 +150,11 @@
}
})
window.__TAURI_INVOKE__('tauri', {
__tauriModule: 'Event',
message: {
cmd: 'listen',
event: 'tauri://window-created',
handler: window.__TAURI__.transformCallback(function (event) {
if (event.payload) {
var windowLabel = event.payload.label
window.__TAURI_METADATA__.__windows.push({
label: windowLabel
})
}
listen('tauri://window-created', function (event) {
if (event.payload) {
var windowLabel = event.payload.label
window.__TAURI_METADATA__.__windows.push({
label: windowLabel
})
}
})

View File

@ -9,6 +9,8 @@
__RAW_bundle_script__
})()
__RAW_listen_function__
__RAW_core_script__
__RAW_event_initialization_script__

View File

@ -1156,7 +1156,7 @@ impl<R: Runtime> Builder<R> {
app.manager.initialize_plugins(&app.handle())?;
let pending_labels = self
let window_labels = self
.pending_windows
.iter()
.map(|p| p.label.clone())
@ -1168,7 +1168,7 @@ impl<R: Runtime> Builder<R> {
for pending in self.pending_windows {
let pending = app
.manager
.prepare_window(app.handle.clone(), pending, &pending_labels)?;
.prepare_window(app.handle.clone(), pending, &window_labels)?;
let detached = app.runtime.as_ref().unwrap().create_window(pending)?;
let _window = app.manager.attach_window(app.handle(), detached);
#[cfg(feature = "updater")]

View File

@ -4,7 +4,11 @@
use super::InvokeContext;
use crate::{
api::ipc::CallbackFn, event::is_event_name_valid, sealed::ManagerBase, Manager, Runtime, Window,
api::ipc::CallbackFn,
event::is_event_name_valid,
event::{listen_js, unlisten_js},
sealed::ManagerBase,
Manager, Runtime,
};
use serde::{de::Deserializer, Deserialize};
use tauri_macros::CommandModule;
@ -54,19 +58,20 @@ impl Cmd {
) -> crate::Result<u64> {
let event_id = rand::random();
context.window.eval(&listen_js(
&context.window,
event.0.clone(),
context.window.manager().event_listeners_object_name(),
format!("'{}'", event.0),
event_id,
handler,
format!("window['_{}']", handler.0),
))?;
context.window.register_js_listener(event.0, event_id);
Ok(event_id)
}
fn unlisten<R: Runtime>(context: InvokeContext<R>, event_id: u64) -> crate::Result<()> {
context
.window
.eval(&unlisten_js(&context.window, event_id))?;
context.window.eval(&unlisten_js(
context.window.manager().event_listeners_object_name(),
event_id,
))?;
context.window.unregister_js_listener(event_id);
Ok(())
}
@ -88,43 +93,3 @@ impl Cmd {
Ok(())
}
}
pub fn unlisten_js<R: Runtime>(window: &Window<R>, event_id: u64) -> String {
format!(
"
for (var event in (window['{listeners}'] || {{}})) {{
var listeners = (window['{listeners}'] || {{}})[event]
if (listeners) {{
window['{listeners}'][event] = window['{listeners}'][event].filter(function (e) {{ return e.id !== {event_id} }})
}}
}}
",
listeners = window.manager().event_listeners_object_name(),
event_id = event_id,
)
}
pub fn listen_js<R: Runtime>(
window: &Window<R>,
event: String,
event_id: u64,
handler: CallbackFn,
) -> String {
format!(
"if (window['{listeners}'] === void 0) {{
window['{listeners}'] = Object.create(null)
}}
if (window['{listeners}']['{event}'] === void 0) {{
window['{listeners}']['{event}'] = []
}}
window['{listeners}']['{event}'].push({{
id: {event_id},
handler: window['_{handler}']
}});
",
listeners = window.manager().event_listeners_object_name(),
event = event,
event_id = event_id,
handler = handler.0
)
}

View File

@ -286,3 +286,43 @@ mod test {
}
}
}
pub fn unlisten_js(listeners_object_name: String, event_id: u64) -> String {
format!(
"
for (var event in (window['{listeners}'] || {{}})) {{
var listeners = (window['{listeners}'] || {{}})[event]
if (listeners) {{
window['{listeners}'][event] = window['{listeners}'][event].filter(function (e) {{ return e.id !== {event_id} }})
}}
}}
",
listeners = listeners_object_name,
event_id = event_id,
)
}
pub fn listen_js(
listeners_object_name: String,
event: String,
event_id: u64,
handler: String,
) -> String {
format!(
"if (window['{listeners}'] === void 0) {{
window['{listeners}'] = Object.create(null)
}}
if (window['{listeners}'][{event}] === void 0) {{
window['{listeners}'][{event}] = []
}}
window['{listeners}'][{event}].push({{
id: {event_id},
handler: {handler}
}});
",
listeners = listeners_object_name,
event = event,
event_id = event_id,
handler = handler
)
}

View File

@ -395,7 +395,7 @@ impl<R: Runtime> WindowManager<R> {
&self,
mut pending: PendingWindow<R>,
label: &str,
pending_labels: &[String],
window_labels: &[String],
app_handle: AppHandle<R>,
) -> crate::Result<PendingWindow<R>> {
let is_init_global = self.inner.config.build.with_global_tauri;
@ -422,6 +422,11 @@ impl<R: Runtime> WindowManager<R> {
let mut webview_attributes = pending.webview_attributes;
let mut window_labels = window_labels.to_vec();
let l = label.to_string();
if !window_labels.contains(&l) {
window_labels.push(l);
}
webview_attributes = webview_attributes
.initialization_script(&self.inner.invoke_initialization_script)
.initialization_script(&format!(
@ -433,7 +438,7 @@ impl<R: Runtime> WindowManager<R> {
}}
}})
"#,
window_labels_array = serde_json::to_string(pending_labels)?,
window_labels_array = serde_json::to_string(&window_labels)?,
current_window_label = serde_json::to_string(&label)?,
))
.initialization_script(&self.initialization_script(&ipc_init,&pattern_init,&plugin_init, is_init_global)?)
@ -809,6 +814,9 @@ impl<R: Runtime> WindowManager<R> {
ipc_script: &'a str,
#[raw]
bundle_script: &'a str,
// A function to immediately listen to an event.
#[raw]
listen_function: &'a str,
#[raw]
core_script: &'a str,
#[raw]
@ -836,6 +844,15 @@ impl<R: Runtime> WindowManager<R> {
pattern_script,
ipc_script,
bundle_script,
listen_function: &format!(
"function listen(eventName, cb) {{ {} }}",
crate::event::listen_js(
self.event_listeners_object_name(),
"eventName".into(),
0,
"window['_' + window.__TAURI__.transformCallback(cb) ]".into()
)
),
core_script: include_str!("../scripts/core.js"),
event_initialization_script: &self.event_initialization_script(),
plugin_initialization_script,
@ -930,7 +947,7 @@ impl<R: Runtime> WindowManager<R> {
&self,
app_handle: AppHandle<R>,
mut pending: PendingWindow<R>,
pending_labels: &[String],
window_labels: &[String],
) -> crate::Result<PendingWindow<R>> {
if self.windows_lock().contains_key(&pending.label) {
return Err(crate::Error::WindowLabelAlreadyExists(pending.label));
@ -982,7 +999,7 @@ impl<R: Runtime> WindowManager<R> {
if is_local {
let label = pending.label.clone();
pending = self.prepare_pending_window(pending, &label, pending_labels, app_handle.clone())?;
pending = self.prepare_pending_window(pending, &label, window_labels, app_handle.clone())?;
pending.ipc_handler = Some(self.prepare_ipc_handler(app_handle.clone()));
}