Skip to content

Commit

Permalink
feat(tauri/Emitter): add emit_str* method to emit serialized data d…
Browse files Browse the repository at this point in the history
…irectly (#12460)

* feat(tauri/Emitter): add `emit_str*` method to emit serialized data

* style: rust fmt
  • Loading branch information
WSH032 authored Jan 26, 2025
1 parent 3dbcbe7 commit abdd558
Show file tree
Hide file tree
Showing 7 changed files with 97 additions and 34 deletions.
5 changes: 5 additions & 0 deletions .changes/emit-str.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
tauri: 'minor:feat'
---

Add `emit_str*` methods to `Emitter` trait to allow emitting JSON serialized data directly.
9 changes: 9 additions & 0 deletions crates/tauri/src/event/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,15 @@ impl EmitArgs {
payload: serde_json::to_string(payload)?,
})
}

pub fn new_str(event: EventName<&str>, payload: String) -> crate::Result<Self> {
#[cfg(feature = "tracing")]
let _span = tracing::debug_span!("window::emit::json").entered();
Ok(EmitArgs {
event: event.into_owned(),
payload,
})
}
}

/// An event that was emitted.
Expand Down
37 changes: 34 additions & 3 deletions crates/tauri/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,7 @@ pub use self::utils::TitleBarStyle;

use self::event::EventName;
pub use self::event::{Event, EventId, EventTarget};
use self::manager::EmitPayload;
pub use {
self::app::{
App, AppHandle, AssetResolver, Builder, CloseRequestApi, RunEvent, UriSchemeContext,
Expand Down Expand Up @@ -940,7 +941,15 @@ pub trait Emitter<R: Runtime>: sealed::ManagerBase<R> {
/// ```
fn emit<S: Serialize + Clone>(&self, event: &str, payload: S) -> Result<()> {
let event = EventName::new(event)?;
self.manager().emit(event, &payload)
let payload = EmitPayload::Serialize(&payload);
self.manager().emit(event, payload)
}

/// Similar to [`Emitter::emit`] but the payload is json serialized.
fn emit_str(&self, event: &str, payload: String) -> Result<()> {
let event = EventName::new(event)?;
let payload = EmitPayload::<()>::Str(payload);
self.manager().emit(event, payload)
}

/// Emits an event to all [targets](EventTarget) matching the given target.
Expand Down Expand Up @@ -971,7 +980,18 @@ pub trait Emitter<R: Runtime>: sealed::ManagerBase<R> {
S: Serialize + Clone,
{
let event = EventName::new(event)?;
self.manager().emit_to(target, event, &payload)
let payload = EmitPayload::Serialize(&payload);
self.manager().emit_to(target, event, payload)
}

/// Similar to [`Emitter::emit_to`] but the payload is json serialized.
fn emit_str_to<I>(&self, target: I, event: &str, payload: String) -> Result<()>
where
I: Into<EventTarget>,
{
let event = EventName::new(event)?;
let payload = EmitPayload::<()>::Str(payload);
self.manager().emit_to(target, event, payload)
}

/// Emits an event to all [targets](EventTarget) based on the given filter.
Expand All @@ -998,7 +1018,18 @@ pub trait Emitter<R: Runtime>: sealed::ManagerBase<R> {
F: Fn(&EventTarget) -> bool,
{
let event = EventName::new(event)?;
self.manager().emit_filter(event, &payload, filter)
let payload = EmitPayload::Serialize(&payload);
self.manager().emit_filter(event, payload, filter)
}

/// Similar to [`Emitter::emit_filter`] but the payload is json serialized.
fn emit_str_filter<F>(&self, event: &str, payload: String, filter: F) -> Result<()>
where
F: Fn(&EventTarget) -> bool,
{
let event = EventName::new(event)?;
let payload = EmitPayload::<()>::Str(payload);
self.manager().emit_filter(event, payload, filter)
}
}

Expand Down
21 changes: 16 additions & 5 deletions crates/tauri/src/manager/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,11 @@ impl<R: Runtime> fmt::Debug for AppManager<R> {
}
}

pub(crate) enum EmitPayload<'a, S: Serialize> {
Serialize(&'a S),
Str(String),
}

impl<R: Runtime> AppManager<R> {
#[allow(clippy::too_many_arguments, clippy::type_complexity)]
pub(crate) fn with_handlers(
Expand Down Expand Up @@ -540,11 +545,14 @@ impl<R: Runtime> AppManager<R> {
pub(crate) fn emit<S: Serialize>(
&self,
event: EventName<&str>,
payload: &S,
payload: EmitPayload<'_, S>,
) -> crate::Result<()> {
#[cfg(feature = "tracing")]
let _span = tracing::debug_span!("emit::run").entered();
let emit_args = EmitArgs::new(event, &payload)?;
let emit_args = match payload {
EmitPayload::Serialize(payload) => EmitArgs::new(event, payload)?,
EmitPayload::Str(payload) => EmitArgs::new_str(event, payload)?,
};

let listeners = self.listeners();
let webviews = self
Expand All @@ -567,7 +575,7 @@ impl<R: Runtime> AppManager<R> {
pub(crate) fn emit_filter<S, F>(
&self,
event: EventName<&str>,
payload: S,
payload: EmitPayload<'_, S>,
filter: F,
) -> crate::Result<()>
where
Expand All @@ -576,7 +584,10 @@ impl<R: Runtime> AppManager<R> {
{
#[cfg(feature = "tracing")]
let _span = tracing::debug_span!("emit::run").entered();
let emit_args = EmitArgs::new(event, &payload)?;
let emit_args = match payload {
EmitPayload::Serialize(payload) => EmitArgs::new(event, payload)?,
EmitPayload::Str(payload) => EmitArgs::new_str(event, payload)?,
};

let listeners = self.listeners();

Expand All @@ -599,7 +610,7 @@ impl<R: Runtime> AppManager<R> {
&self,
target: I,
event: EventName<&str>,
payload: &S,
payload: EmitPayload<'_, S>,
) -> crate::Result<()>
where
I: Into<EventTarget>,
Expand Down
29 changes: 16 additions & 13 deletions crates/tauri/src/manager/webview.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ use crate::{

use super::{
window::{DragDropPayload, DRAG_DROP_EVENT, DRAG_ENTER_EVENT, DRAG_LEAVE_EVENT, DRAG_OVER_EVENT},
AppManager,
{AppManager, EmitPayload},
};

// we need to proxy the dev server on mobile because we can't use `localhost`, so we use the local IP address
Expand Down Expand Up @@ -631,12 +631,14 @@ impl<R: Runtime> WebviewManager<R> {
.expect("failed to run on_webview_created hook");
}

let _ = webview.manager.emit(
crate::EventName::from_str("tauri://webview-created"),
&Some(crate::webview::CreatedEvent {
label: webview.label().into(),
}),
);
let event = crate::EventName::from_str("tauri://webview-created");
let payload = Some(crate::webview::CreatedEvent {
label: webview.label().into(),
});

let _ = webview
.manager
.emit(event, EmitPayload::Serialize(&payload));

webview
}
Expand All @@ -660,12 +662,13 @@ impl<R: Runtime> WebviewManager<R> {

impl<R: Runtime> Webview<R> {
/// Emits event to [`EventTarget::Window`] and [`EventTarget::WebviewWindow`]
fn emit_to_webview<S: Serialize + Clone>(
fn emit_to_webview<S: Serialize>(
&self,
event: crate::EventName<&str>,
payload: S,
payload: &S,
) -> crate::Result<()> {
let window_label = self.label();
let payload = EmitPayload::Serialize(payload);
self
.manager()
.emit_filter(event, payload, |target| match target {
Expand All @@ -685,14 +688,14 @@ fn on_webview_event<R: Runtime>(webview: &Webview<R>, event: &WebviewEvent) -> c
paths: Some(paths),
position,
};
webview.emit_to_webview(DRAG_ENTER_EVENT, payload)?
webview.emit_to_webview(DRAG_ENTER_EVENT, &payload)?
}
DragDropEvent::Over { position } => {
let payload = DragDropPayload {
position,
paths: None,
};
webview.emit_to_webview(DRAG_OVER_EVENT, payload)?
webview.emit_to_webview(DRAG_OVER_EVENT, &payload)?
}
DragDropEvent::Drop { paths, position } => {
let scopes = webview.state::<Scopes>();
Expand All @@ -707,9 +710,9 @@ fn on_webview_event<R: Runtime>(webview: &Webview<R>, event: &WebviewEvent) -> c
paths: Some(paths),
position,
};
webview.emit_to_webview(DRAG_DROP_EVENT, payload)?
webview.emit_to_webview(DRAG_DROP_EVENT, &payload)?
}
DragDropEvent::Leave => webview.emit_to_webview(DRAG_LEAVE_EVENT, ())?,
DragDropEvent::Leave => webview.emit_to_webview(DRAG_LEAVE_EVENT, &())?,
_ => unimplemented!(),
},
}
Expand Down
17 changes: 11 additions & 6 deletions crates/tauri/src/manager/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ use crate::{
EventLoopMessage, EventTarget, Manager, Runtime, Scopes, Window, WindowEvent,
};

use super::EmitPayload;

const WINDOW_RESIZED_EVENT: EventName<&str> = EventName::from_str("tauri://resize");
const WINDOW_MOVED_EVENT: EventName<&str> = EventName::from_str("tauri://move");
const WINDOW_CLOSE_REQUESTED_EVENT: EventName<&str> =
Expand Down Expand Up @@ -128,6 +130,7 @@ impl<R: Runtime> Window<R> {
/// Emits event to [`EventTarget::Window`] and [`EventTarget::WebviewWindow`]
fn emit_to_window<S: Serialize>(&self, event: EventName<&str>, payload: &S) -> crate::Result<()> {
let window_label = self.label();
let payload = EmitPayload::Serialize(payload);
self
.manager()
.emit_filter(event, payload, |target| match target {
Expand Down Expand Up @@ -200,7 +203,7 @@ fn on_window_event<R: Runtime>(window: &Window<R>, event: &WindowEvent) -> crate
window.manager().emit_to(
EventTarget::labeled(window.label()),
DRAG_ENTER_EVENT,
&payload,
EmitPayload::Serialize(&payload),
)?
} else {
window.emit_to_window(DRAG_ENTER_EVENT, &payload)?
Expand All @@ -216,7 +219,7 @@ fn on_window_event<R: Runtime>(window: &Window<R>, event: &WindowEvent) -> crate
window.manager().emit_to(
EventTarget::labeled(window.label()),
DRAG_OVER_EVENT,
&payload,
EmitPayload::Serialize(&payload),
)?
} else {
window.emit_to_window(DRAG_OVER_EVENT, &payload)?
Expand All @@ -241,7 +244,7 @@ fn on_window_event<R: Runtime>(window: &Window<R>, event: &WindowEvent) -> crate
window.manager().emit_to(
EventTarget::labeled(window.label()),
DRAG_DROP_EVENT,
&payload,
EmitPayload::Serialize(&payload),
)?
} else {
window.emit_to_window(DRAG_DROP_EVENT, &payload)?
Expand All @@ -250,9 +253,11 @@ fn on_window_event<R: Runtime>(window: &Window<R>, event: &WindowEvent) -> crate
DragDropEvent::Leave => {
if window.is_webview_window() {
// use underlying manager, otherwise have to recheck EventName
window
.manager()
.emit_to(EventTarget::labeled(window.label()), DRAG_LEAVE_EVENT, &())?
window.manager().emit_to(
EventTarget::labeled(window.label()),
DRAG_LEAVE_EVENT,
EmitPayload::Serialize(&()),
)?
} else {
window.emit_to_window(DRAG_LEAVE_EVENT, &())?
}
Expand Down
13 changes: 6 additions & 7 deletions crates/tauri/src/window/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use crate::{
app::AppHandle,
event::{Event, EventId, EventTarget},
ipc::{CommandArg, CommandItem, InvokeError},
manager::AppManager,
manager::{AppManager, EmitPayload},
runtime::{
monitor::Monitor as RuntimeMonitor,
window::{DetachedWindow, PendingWindow, WindowBuilder as _},
Expand Down Expand Up @@ -404,12 +404,11 @@ tauri::Builder::default()
let window_label = window.label().to_string();
// run on the main thread to fix a deadlock on webview.eval if the tracing feature is enabled
let _ = window.run_on_main_thread(move || {
let _ = app_manager.emit(
crate::EventName::from_str("tauri://window-created"),
&Some(crate::webview::CreatedEvent {
label: window_label,
}),
);
let event = crate::EventName::from_str("tauri://window-created");
let payload = Some(crate::webview::CreatedEvent {
label: window_label,
});
let _ = app_manager.emit(event, EmitPayload::Serialize(&payload));
});

Ok(window)
Expand Down

0 comments on commit abdd558

Please sign in to comment.