소스 검색

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

Lucas Fernandes Nogueira 3 년 전
부모
커밋
878b8b9a1f
7개의 변경된 파일87개의 추가작업 그리고 65개의 파일을 삭제
  1. 5 0
      .changes/fix-window-created-listen.md
  2. 5 12
      core/tauri/scripts/core.js
  3. 2 0
      core/tauri/scripts/init.js
  4. 2 2
      core/tauri/src/app.rs
  5. 12 47
      core/tauri/src/endpoints/event.rs
  6. 40 0
      core/tauri/src/event.rs
  7. 21 4
      core/tauri/src/manager.rs

+ 5 - 0
.changes/fix-window-created-listen.md

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

+ 5 - 12
core/tauri/scripts/core.js

@@ -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
       })
     }
   })

+ 2 - 0
core/tauri/scripts/init.js

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

+ 2 - 2
core/tauri/src/app.rs

@@ -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")]

+ 12 - 47
core/tauri/src/endpoints/event.rs

@@ -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
-  )
-}

+ 40 - 0
core/tauri/src/event.rs

@@ -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
+  )
+}

+ 21 - 4
core/tauri/src/manager.rs

@@ -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()));
     }