Skip to content

Commit

Permalink
feat(core): Manager::emit_filter and optimize serialization (#7512)
Browse files Browse the repository at this point in the history
Co-authored-by: Lucas Nogueira <[email protected]>
  • Loading branch information
icambron and lucasfernog authored Aug 8, 2023
1 parent a6b52e4 commit eeb6be5
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 13 deletions.
5 changes: 5 additions & 0 deletions .changes/add-manager-emit-filter.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'tauri': 'minor:feat'
---

Add `tauri::Manager::emit_filter` and only serialize once when emitting to multiple windows.
22 changes: 21 additions & 1 deletion core/tauri/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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`].
Expand All @@ -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
Expand Down
10 changes: 7 additions & 3 deletions core/tauri/src/manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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};
Expand Down Expand Up @@ -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<()> {
Expand Down
33 changes: 24 additions & 9 deletions core/tauri/src/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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")]
Expand Down Expand Up @@ -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(())
}
Expand Down

0 comments on commit eeb6be5

Please sign in to comment.