Skip to content

Commit abdd558

Browse files
authored
feat(tauri/Emitter): add emit_str* method to emit serialized data directly (#12460)
* feat(tauri/Emitter): add `emit_str*` method to emit serialized data * style: rust fmt
1 parent 3dbcbe7 commit abdd558

File tree

7 files changed

+97
-34
lines changed

7 files changed

+97
-34
lines changed

.changes/emit-str.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
tauri: 'minor:feat'
3+
---
4+
5+
Add `emit_str*` methods to `Emitter` trait to allow emitting JSON serialized data directly.

crates/tauri/src/event/mod.rs

+9
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,15 @@ impl EmitArgs {
128128
payload: serde_json::to_string(payload)?,
129129
})
130130
}
131+
132+
pub fn new_str(event: EventName<&str>, payload: String) -> crate::Result<Self> {
133+
#[cfg(feature = "tracing")]
134+
let _span = tracing::debug_span!("window::emit::json").entered();
135+
Ok(EmitArgs {
136+
event: event.into_owned(),
137+
payload,
138+
})
139+
}
131140
}
132141

133142
/// An event that was emitted.

crates/tauri/src/lib.rs

+34-3
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,7 @@ pub use self::utils::TitleBarStyle;
210210

211211
use self::event::EventName;
212212
pub use self::event::{Event, EventId, EventTarget};
213+
use self::manager::EmitPayload;
213214
pub use {
214215
self::app::{
215216
App, AppHandle, AssetResolver, Builder, CloseRequestApi, RunEvent, UriSchemeContext,
@@ -940,7 +941,15 @@ pub trait Emitter<R: Runtime>: sealed::ManagerBase<R> {
940941
/// ```
941942
fn emit<S: Serialize + Clone>(&self, event: &str, payload: S) -> Result<()> {
942943
let event = EventName::new(event)?;
943-
self.manager().emit(event, &payload)
944+
let payload = EmitPayload::Serialize(&payload);
945+
self.manager().emit(event, payload)
946+
}
947+
948+
/// Similar to [`Emitter::emit`] but the payload is json serialized.
949+
fn emit_str(&self, event: &str, payload: String) -> Result<()> {
950+
let event = EventName::new(event)?;
951+
let payload = EmitPayload::<()>::Str(payload);
952+
self.manager().emit(event, payload)
944953
}
945954

946955
/// Emits an event to all [targets](EventTarget) matching the given target.
@@ -971,7 +980,18 @@ pub trait Emitter<R: Runtime>: sealed::ManagerBase<R> {
971980
S: Serialize + Clone,
972981
{
973982
let event = EventName::new(event)?;
974-
self.manager().emit_to(target, event, &payload)
983+
let payload = EmitPayload::Serialize(&payload);
984+
self.manager().emit_to(target, event, payload)
985+
}
986+
987+
/// Similar to [`Emitter::emit_to`] but the payload is json serialized.
988+
fn emit_str_to<I>(&self, target: I, event: &str, payload: String) -> Result<()>
989+
where
990+
I: Into<EventTarget>,
991+
{
992+
let event = EventName::new(event)?;
993+
let payload = EmitPayload::<()>::Str(payload);
994+
self.manager().emit_to(target, event, payload)
975995
}
976996

977997
/// Emits an event to all [targets](EventTarget) based on the given filter.
@@ -998,7 +1018,18 @@ pub trait Emitter<R: Runtime>: sealed::ManagerBase<R> {
9981018
F: Fn(&EventTarget) -> bool,
9991019
{
10001020
let event = EventName::new(event)?;
1001-
self.manager().emit_filter(event, &payload, filter)
1021+
let payload = EmitPayload::Serialize(&payload);
1022+
self.manager().emit_filter(event, payload, filter)
1023+
}
1024+
1025+
/// Similar to [`Emitter::emit_filter`] but the payload is json serialized.
1026+
fn emit_str_filter<F>(&self, event: &str, payload: String, filter: F) -> Result<()>
1027+
where
1028+
F: Fn(&EventTarget) -> bool,
1029+
{
1030+
let event = EventName::new(event)?;
1031+
let payload = EmitPayload::<()>::Str(payload);
1032+
self.manager().emit_filter(event, payload, filter)
10021033
}
10031034
}
10041035

crates/tauri/src/manager/mod.rs

+16-5
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,11 @@ impl<R: Runtime> fmt::Debug for AppManager<R> {
244244
}
245245
}
246246

247+
pub(crate) enum EmitPayload<'a, S: Serialize> {
248+
Serialize(&'a S),
249+
Str(String),
250+
}
251+
247252
impl<R: Runtime> AppManager<R> {
248253
#[allow(clippy::too_many_arguments, clippy::type_complexity)]
249254
pub(crate) fn with_handlers(
@@ -540,11 +545,14 @@ impl<R: Runtime> AppManager<R> {
540545
pub(crate) fn emit<S: Serialize>(
541546
&self,
542547
event: EventName<&str>,
543-
payload: &S,
548+
payload: EmitPayload<'_, S>,
544549
) -> crate::Result<()> {
545550
#[cfg(feature = "tracing")]
546551
let _span = tracing::debug_span!("emit::run").entered();
547-
let emit_args = EmitArgs::new(event, &payload)?;
552+
let emit_args = match payload {
553+
EmitPayload::Serialize(payload) => EmitArgs::new(event, payload)?,
554+
EmitPayload::Str(payload) => EmitArgs::new_str(event, payload)?,
555+
};
548556

549557
let listeners = self.listeners();
550558
let webviews = self
@@ -567,7 +575,7 @@ impl<R: Runtime> AppManager<R> {
567575
pub(crate) fn emit_filter<S, F>(
568576
&self,
569577
event: EventName<&str>,
570-
payload: S,
578+
payload: EmitPayload<'_, S>,
571579
filter: F,
572580
) -> crate::Result<()>
573581
where
@@ -576,7 +584,10 @@ impl<R: Runtime> AppManager<R> {
576584
{
577585
#[cfg(feature = "tracing")]
578586
let _span = tracing::debug_span!("emit::run").entered();
579-
let emit_args = EmitArgs::new(event, &payload)?;
587+
let emit_args = match payload {
588+
EmitPayload::Serialize(payload) => EmitArgs::new(event, payload)?,
589+
EmitPayload::Str(payload) => EmitArgs::new_str(event, payload)?,
590+
};
580591

581592
let listeners = self.listeners();
582593

@@ -599,7 +610,7 @@ impl<R: Runtime> AppManager<R> {
599610
&self,
600611
target: I,
601612
event: EventName<&str>,
602-
payload: &S,
613+
payload: EmitPayload<'_, S>,
603614
) -> crate::Result<()>
604615
where
605616
I: Into<EventTarget>,

crates/tauri/src/manager/webview.rs

+16-13
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ use crate::{
3030

3131
use super::{
3232
window::{DragDropPayload, DRAG_DROP_EVENT, DRAG_ENTER_EVENT, DRAG_LEAVE_EVENT, DRAG_OVER_EVENT},
33-
AppManager,
33+
{AppManager, EmitPayload},
3434
};
3535

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

634-
let _ = webview.manager.emit(
635-
crate::EventName::from_str("tauri://webview-created"),
636-
&Some(crate::webview::CreatedEvent {
637-
label: webview.label().into(),
638-
}),
639-
);
634+
let event = crate::EventName::from_str("tauri://webview-created");
635+
let payload = Some(crate::webview::CreatedEvent {
636+
label: webview.label().into(),
637+
});
638+
639+
let _ = webview
640+
.manager
641+
.emit(event, EmitPayload::Serialize(&payload));
640642

641643
webview
642644
}
@@ -660,12 +662,13 @@ impl<R: Runtime> WebviewManager<R> {
660662

661663
impl<R: Runtime> Webview<R> {
662664
/// Emits event to [`EventTarget::Window`] and [`EventTarget::WebviewWindow`]
663-
fn emit_to_webview<S: Serialize + Clone>(
665+
fn emit_to_webview<S: Serialize>(
664666
&self,
665667
event: crate::EventName<&str>,
666-
payload: S,
668+
payload: &S,
667669
) -> crate::Result<()> {
668670
let window_label = self.label();
671+
let payload = EmitPayload::Serialize(payload);
669672
self
670673
.manager()
671674
.emit_filter(event, payload, |target| match target {
@@ -685,14 +688,14 @@ fn on_webview_event<R: Runtime>(webview: &Webview<R>, event: &WebviewEvent) -> c
685688
paths: Some(paths),
686689
position,
687690
};
688-
webview.emit_to_webview(DRAG_ENTER_EVENT, payload)?
691+
webview.emit_to_webview(DRAG_ENTER_EVENT, &payload)?
689692
}
690693
DragDropEvent::Over { position } => {
691694
let payload = DragDropPayload {
692695
position,
693696
paths: None,
694697
};
695-
webview.emit_to_webview(DRAG_OVER_EVENT, payload)?
698+
webview.emit_to_webview(DRAG_OVER_EVENT, &payload)?
696699
}
697700
DragDropEvent::Drop { paths, position } => {
698701
let scopes = webview.state::<Scopes>();
@@ -707,9 +710,9 @@ fn on_webview_event<R: Runtime>(webview: &Webview<R>, event: &WebviewEvent) -> c
707710
paths: Some(paths),
708711
position,
709712
};
710-
webview.emit_to_webview(DRAG_DROP_EVENT, payload)?
713+
webview.emit_to_webview(DRAG_DROP_EVENT, &payload)?
711714
}
712-
DragDropEvent::Leave => webview.emit_to_webview(DRAG_LEAVE_EVENT, ())?,
715+
DragDropEvent::Leave => webview.emit_to_webview(DRAG_LEAVE_EVENT, &())?,
713716
_ => unimplemented!(),
714717
},
715718
}

crates/tauri/src/manager/window.rs

+11-6
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ use crate::{
2121
EventLoopMessage, EventTarget, Manager, Runtime, Scopes, Window, WindowEvent,
2222
};
2323

24+
use super::EmitPayload;
25+
2426
const WINDOW_RESIZED_EVENT: EventName<&str> = EventName::from_str("tauri://resize");
2527
const WINDOW_MOVED_EVENT: EventName<&str> = EventName::from_str("tauri://move");
2628
const WINDOW_CLOSE_REQUESTED_EVENT: EventName<&str> =
@@ -128,6 +130,7 @@ impl<R: Runtime> Window<R> {
128130
/// Emits event to [`EventTarget::Window`] and [`EventTarget::WebviewWindow`]
129131
fn emit_to_window<S: Serialize>(&self, event: EventName<&str>, payload: &S) -> crate::Result<()> {
130132
let window_label = self.label();
133+
let payload = EmitPayload::Serialize(payload);
131134
self
132135
.manager()
133136
.emit_filter(event, payload, |target| match target {
@@ -200,7 +203,7 @@ fn on_window_event<R: Runtime>(window: &Window<R>, event: &WindowEvent) -> crate
200203
window.manager().emit_to(
201204
EventTarget::labeled(window.label()),
202205
DRAG_ENTER_EVENT,
203-
&payload,
206+
EmitPayload::Serialize(&payload),
204207
)?
205208
} else {
206209
window.emit_to_window(DRAG_ENTER_EVENT, &payload)?
@@ -216,7 +219,7 @@ fn on_window_event<R: Runtime>(window: &Window<R>, event: &WindowEvent) -> crate
216219
window.manager().emit_to(
217220
EventTarget::labeled(window.label()),
218221
DRAG_OVER_EVENT,
219-
&payload,
222+
EmitPayload::Serialize(&payload),
220223
)?
221224
} else {
222225
window.emit_to_window(DRAG_OVER_EVENT, &payload)?
@@ -241,7 +244,7 @@ fn on_window_event<R: Runtime>(window: &Window<R>, event: &WindowEvent) -> crate
241244
window.manager().emit_to(
242245
EventTarget::labeled(window.label()),
243246
DRAG_DROP_EVENT,
244-
&payload,
247+
EmitPayload::Serialize(&payload),
245248
)?
246249
} else {
247250
window.emit_to_window(DRAG_DROP_EVENT, &payload)?
@@ -250,9 +253,11 @@ fn on_window_event<R: Runtime>(window: &Window<R>, event: &WindowEvent) -> crate
250253
DragDropEvent::Leave => {
251254
if window.is_webview_window() {
252255
// use underlying manager, otherwise have to recheck EventName
253-
window
254-
.manager()
255-
.emit_to(EventTarget::labeled(window.label()), DRAG_LEAVE_EVENT, &())?
256+
window.manager().emit_to(
257+
EventTarget::labeled(window.label()),
258+
DRAG_LEAVE_EVENT,
259+
EmitPayload::Serialize(&()),
260+
)?
256261
} else {
257262
window.emit_to_window(DRAG_LEAVE_EVENT, &())?
258263
}

crates/tauri/src/window/mod.rs

+6-7
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use crate::{
1919
app::AppHandle,
2020
event::{Event, EventId, EventTarget},
2121
ipc::{CommandArg, CommandItem, InvokeError},
22-
manager::AppManager,
22+
manager::{AppManager, EmitPayload},
2323
runtime::{
2424
monitor::Monitor as RuntimeMonitor,
2525
window::{DetachedWindow, PendingWindow, WindowBuilder as _},
@@ -404,12 +404,11 @@ tauri::Builder::default()
404404
let window_label = window.label().to_string();
405405
// run on the main thread to fix a deadlock on webview.eval if the tracing feature is enabled
406406
let _ = window.run_on_main_thread(move || {
407-
let _ = app_manager.emit(
408-
crate::EventName::from_str("tauri://window-created"),
409-
&Some(crate::webview::CreatedEvent {
410-
label: window_label,
411-
}),
412-
);
407+
let event = crate::EventName::from_str("tauri://window-created");
408+
let payload = Some(crate::webview::CreatedEvent {
409+
label: window_label,
410+
});
411+
let _ = app_manager.emit(event, EmitPayload::Serialize(&payload));
413412
});
414413

415414
Ok(window)

0 commit comments

Comments
 (0)