Эх сурвалжийг харах

feat(core): Manager::emit_filter and optimize serialization (#7512)

Co-authored-by: Lucas Nogueira <lucas@tauri.studio>
Isaac Cambron 2 жил өмнө
parent
commit
eeb6be5422

+ 5 - 0
.changes/add-manager-emit-filter.md

@@ -0,0 +1,5 @@
+---
+'tauri': 'minor:feat'
+---
+
+Add `tauri::Manager::emit_filter` and only serialize once when emitting to multiple windows.

+ 21 - 1
core/tauri/src/lib.rs

@@ -610,7 +610,7 @@ pub trait Manager<R: Runtime>: sealed::ManagerBase<R> {
     self.manager().config()
   }
 
-  /// Emits a event to all windows.
+  /// Emits an event to all windows.
   ///
   /// Only the webviews receives this event.
   /// To trigger Rust listeners, use [`Self::trigger_global`], [`Window::trigger`] or [`Window::emit_and_trigger`].
@@ -629,6 +629,26 @@ pub trait Manager<R: Runtime>: sealed::ManagerBase<R> {
     self.manager().emit_filter(event, None, payload, |_| true)
   }
 
+  /// Emits an event to windows matching the filter critera.
+  ///
+  /// # Examples
+  /// ```
+  /// use tauri::Manager;
+  ///
+  /// #[tauri::command]
+  /// fn synchronize(app: tauri::AppHandle) {
+  ///   // emits the synchronized event to all windows
+  ///   app.emit_filter("synchronized", (), |w| w.label().starts_with("foo-"));
+  /// }
+  /// ```
+  fn emit_filter<S, F>(&self, event: &str, payload: S, filter: F) -> Result<()>
+  where
+    S: Serialize + Clone,
+    F: Fn(&Window<R>) -> bool,
+  {
+    self.manager().emit_filter(event, None, payload, filter)
+  }
+
   /// Emits an event to the window with the specified label.
   ///
   /// # Examples

+ 7 - 3
core/tauri/src/manager.rs

@@ -25,7 +25,6 @@ use tauri_utils::{
   html::{SCRIPT_NONCE_TOKEN, STYLE_NONCE_TOKEN},
 };
 
-use crate::app::{GlobalMenuEventListener, WindowMenuEvent};
 use crate::hooks::IpcJavascript;
 #[cfg(feature = "isolation")]
 use crate::hooks::IsolationJavascript;
@@ -51,6 +50,10 @@ use crate::{
   Context, EventLoopMessage, Icon, Invoke, Manager, Pattern, Runtime, Scopes, StateManager, Window,
   WindowEvent,
 };
+use crate::{
+  app::{GlobalMenuEventListener, WindowMenuEvent},
+  window::WindowEmitArgs,
+};
 
 #[cfg(any(target_os = "linux", target_os = "windows"))]
 use crate::api::path::{resolve_path, BaseDirectory};
@@ -1102,12 +1105,13 @@ impl<R: Runtime> WindowManager<R> {
     S: Serialize + Clone,
     F: Fn(&Window<R>) -> bool,
   {
+    let emit_args = WindowEmitArgs::from(event, source_window_label, payload)?;
     assert_event_name_is_valid(event);
     self
-      .windows_lock()
+      .windows()
       .values()
       .filter(|&w| filter(w))
-      .try_for_each(|window| window.emit_internal(event, source_window_label, payload.clone()))
+      .try_for_each(|window| window.emit_internal(&emit_args))
   }
 
   pub fn eval_script_all<S: Into<String>>(&self, script: S) -> crate::Result<()> {

+ 24 - 9
core/tauri/src/window.rs

@@ -56,6 +56,26 @@ struct WindowCreatedEvent {
   label: String,
 }
 
+pub(crate) struct WindowEmitArgs {
+  pub event: String,
+  pub source_window_label: String,
+  pub payload: String,
+}
+
+impl WindowEmitArgs {
+  pub fn from<S: Serialize>(
+    event: &str,
+    source_window_label: Option<&str>,
+    payload: S,
+  ) -> crate::Result<Self> {
+    Ok(WindowEmitArgs {
+      event: serde_json::to_string(event)?,
+      source_window_label: serde_json::to_string(&source_window_label)?,
+      payload: serde_json::to_string(&payload)?,
+    })
+  }
+}
+
 /// Monitor descriptor.
 #[derive(Debug, Clone, Serialize)]
 #[serde(rename_all = "camelCase")]
@@ -1764,18 +1784,13 @@ impl<R: Runtime> Window<R> {
     self.emit(event, payload)
   }
 
-  pub(crate) fn emit_internal<S: Serialize>(
-    &self,
-    event: &str,
-    source_window_label: Option<&str>,
-    payload: S,
-  ) -> crate::Result<()> {
+  pub(crate) fn emit_internal(&self, emit_args: &WindowEmitArgs) -> crate::Result<()> {
     self.eval(&format!(
       "(function () {{ const fn = window['{}']; fn && fn({{event: {}, windowLabel: {}, payload: {}}}) }})()",
       self.manager.event_emit_function_name(),
-      serde_json::to_string(event)?,
-      serde_json::to_string(&source_window_label)?,
-      serde_json::to_value(payload)?,
+      emit_args.event,
+      emit_args.source_window_label,
+      emit_args.payload
     ))?;
     Ok(())
   }