Skip to content

Commit 181e132

Browse files
refactor(core): simplify usage of app event and window label types (#1623)
Co-authored-by: chip reed <chip@chip.sh>
1 parent af6411d commit 181e132

File tree

11 files changed

+162
-101
lines changed

11 files changed

+162
-101
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"tauri": patch
3+
---
4+
5+
Simplify usage of app event and window label types.

core/tauri/src/endpoints/event.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,12 +52,12 @@ impl Cmd {
5252
});
5353

5454
// dispatch the event to Rust listeners
55-
window.trigger(e.clone(), payload.clone());
55+
window.trigger(&e, payload.clone());
5656

5757
if let Some(target) = window_label {
58-
window.emit_to(&target, e, payload)?;
58+
window.emit_to(&target, &e, payload)?;
5959
} else {
60-
window.emit_all(e, payload)?;
60+
window.emit_all(&e, payload)?;
6161
}
6262
Ok(().into())
6363
}

core/tauri/src/endpoints/window.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ struct WindowCreatedEvent {
9999

100100
impl Cmd {
101101
#[allow(dead_code)]
102-
pub async fn run<M: Params>(self, window: Window<M>) -> crate::Result<InvokeResponse> {
102+
pub async fn run<P: Params>(self, window: Window<P>) -> crate::Result<InvokeResponse> {
103103
if cfg!(not(window_all)) {
104104
Err(crate::Error::ApiNotAllowlisted("window > all".to_string()))
105105
} else {
@@ -114,7 +114,7 @@ impl Cmd {
114114
Self::CreateWebview { options } => {
115115
let mut window = window;
116116
// Panic if the user's `Tag` type decided to return an error while parsing.
117-
let label: M::Label = options.label.parse().unwrap_or_else(|_| {
117+
let label: P::Label = options.label.parse().unwrap_or_else(|_| {
118118
panic!(
119119
"Window module received unknown window label: {}",
120120
options.label
@@ -124,13 +124,15 @@ impl Cmd {
124124
let url = options.url.clone();
125125
let pending =
126126
crate::runtime::window::PendingWindow::with_config(options, label.clone(), url);
127-
window.create_window(pending)?.emit_others_internal(
128-
"tauri://window-created".to_string(),
127+
128+
window.create_window(pending)?.emit_others(
129+
&crate::runtime::manager::tauri_event::<P::Event>("tauri://window-created"),
129130
Some(WindowCreatedEvent {
130131
label: label.to_string(),
131132
}),
132133
)?;
133134
}
135+
134136
Self::SetResizable { resizable } => window.set_resizable(resizable)?,
135137
Self::SetTitle { title } => window.set_title(&title)?,
136138
Self::Maximize => window.maximize()?,

core/tauri/src/event.rs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@
22
// SPDX-License-Identifier: Apache-2.0
33
// SPDX-License-Identifier: MIT
44

5-
use crate::runtime::tag::Tag;
5+
use crate::runtime::tag::{Tag, TagRef};
66
use std::{
7+
borrow::Borrow,
78
boxed::Box,
89
collections::HashMap,
910
fmt,
@@ -134,7 +135,7 @@ impl<Event: Tag, Window: Tag> Listeners<Event, Window> {
134135
match action {
135136
Pending::Unlisten(id) => self.unlisten(id),
136137
Pending::Listen(id, event, handler) => self.listen_(id, event, handler),
137-
Pending::Trigger(event, window, payload) => self.trigger(event, window, payload),
138+
Pending::Trigger(ref event, window, payload) => self.trigger(event, window, payload),
138139
}
139140
}
140141
}
@@ -191,12 +192,16 @@ impl<Event: Tag, Window: Tag> Listeners<Event, Window> {
191192
}
192193

193194
/// Triggers the given global event with its payload.
194-
pub(crate) fn trigger(&self, event: Event, window: Option<Window>, payload: Option<String>) {
195+
pub(crate) fn trigger<E>(&self, event: &E, window: Option<Window>, payload: Option<String>)
196+
where
197+
E: TagRef<Event> + ?Sized,
198+
Event: Borrow<E>,
199+
{
195200
let mut maybe_pending = false;
196201
match self.inner.handlers.try_lock() {
197-
Err(_) => self.insert_pending(Pending::Trigger(event, window, payload)),
202+
Err(_) => self.insert_pending(Pending::Trigger(event.to_owned(), window, payload)),
198203
Ok(lock) => {
199-
if let Some(handlers) = lock.get(&event) {
204+
if let Some(handlers) = lock.get(event) {
200205
for (&id, handler) in handlers {
201206
if window.is_none() || window == handler.window {
202207
maybe_pending = true;
@@ -280,7 +285,7 @@ mod test {
280285
// call listen with e and the event_fn dummy func
281286
listeners.listen(e.clone(), None, event_fn);
282287
// call on event with e and d.
283-
listeners.trigger(e, None, Some(d));
288+
listeners.trigger(&e, None, Some(d));
284289

285290
// lock the mutex
286291
let l = listeners.inner.handlers.lock().unwrap();

core/tauri/src/lib.rs

Lines changed: 34 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ pub type SyncTask = Box<dyn FnOnce() + Send>;
3939
use crate::api::assets::Assets;
4040
use crate::api::config::Config;
4141
use crate::event::{Event, EventHandler};
42-
use crate::runtime::tag::Tag;
42+
use crate::runtime::tag::{Tag, TagRef};
4343
use crate::runtime::window::PendingWindow;
4444
use crate::runtime::{Dispatch, Runtime};
4545
use serde::Serialize;
@@ -51,10 +51,12 @@ pub use {
5151
api::config::WindowUrl,
5252
hooks::{InvokeHandler, InvokeMessage, OnPageLoad, PageLoadPayload, SetupHook},
5353
runtime::app::{App, Builder},
54+
runtime::flavors::wry::Wry,
5455
runtime::webview::Attributes,
5556
runtime::window::export::Window,
5657
};
5758

59+
use std::borrow::Borrow;
5860
/// Reads the config file at compile time and generates a [`Context`] based on its content.
5961
///
6062
/// The default config file path is a `tauri.conf.json` file inside the Cargo manifest directory of
@@ -130,31 +132,39 @@ pub trait Params: sealed::ParamsBase {
130132
/// Manages a running application.
131133
///
132134
/// TODO: expand these docs
133-
pub trait Manager<M: Params>: sealed::ManagerBase<M> {
135+
pub trait Manager<P: Params>: sealed::ManagerBase<P> {
134136
/// The [`Config`] the manager was created with.
135137
fn config(&self) -> &Config {
136138
self.manager().config()
137139
}
138140

139141
/// Emits a event to all windows.
140-
fn emit_all<S: Serialize + Clone>(&self, event: M::Event, payload: Option<S>) -> Result<()> {
142+
fn emit_all<E, S>(&self, event: &E, payload: Option<S>) -> Result<()>
143+
where
144+
E: TagRef<P::Event> + ?Sized,
145+
S: Serialize + Clone,
146+
{
141147
self.manager().emit_filter(event, payload, |_| true)
142148
}
143149

144150
/// Emits an event to a window with the specified label.
145-
fn emit_to<S: Serialize + Clone>(
151+
fn emit_to<E, L, S: Serialize + Clone>(
146152
&self,
147-
label: &M::Label,
148-
event: M::Event,
153+
label: &L,
154+
event: &E,
149155
payload: Option<S>,
150-
) -> Result<()> {
156+
) -> Result<()>
157+
where
158+
L: TagRef<P::Label> + ?Sized,
159+
E: TagRef<P::Event> + ?Sized,
160+
{
151161
self
152162
.manager()
153-
.emit_filter(event, payload, |w| w.label() == label)
163+
.emit_filter(event, payload, |w| label == w.label())
154164
}
155165

156166
/// Creates a new [`Window`] on the [`Runtime`] and attaches it to the [`Manager`].
157-
fn create_window(&mut self, pending: PendingWindow<M>) -> Result<Window<M>> {
167+
fn create_window(&mut self, pending: PendingWindow<P>) -> Result<Window<P>> {
158168
use sealed::RuntimeOrDispatch::*;
159169

160170
let labels = self.manager().labels().into_iter().collect::<Vec<_>>();
@@ -167,23 +177,27 @@ pub trait Manager<M: Params>: sealed::ManagerBase<M> {
167177
}
168178

169179
/// Listen to a global event.
170-
fn listen_global<F>(&self, event: M::Event, handler: F) -> EventHandler
180+
fn listen_global<E: Into<P::Event>, F>(&self, event: E, handler: F) -> EventHandler
171181
where
172182
F: Fn(Event) + Send + 'static,
173183
{
174-
self.manager().listen(event, None, handler)
184+
self.manager().listen(event.into(), None, handler)
175185
}
176186

177187
/// Listen to a global event only once.
178-
fn once_global<F>(&self, event: M::Event, handler: F) -> EventHandler
188+
fn once_global<E: Into<P::Event>, F>(&self, event: E, handler: F) -> EventHandler
179189
where
180190
F: Fn(Event) + Send + 'static,
181191
{
182-
self.manager().once(event, None, handler)
192+
self.manager().once(event.into(), None, handler)
183193
}
184194

185195
/// Trigger a global event.
186-
fn trigger_global(&self, event: M::Event, data: Option<String>) {
196+
fn trigger_global<E>(&self, event: &E, data: Option<String>)
197+
where
198+
E: TagRef<P::Event> + ?Sized,
199+
P::Event: Borrow<E>,
200+
{
187201
self.manager().trigger(event, None, data)
188202
}
189203

@@ -193,12 +207,16 @@ pub trait Manager<M: Params>: sealed::ManagerBase<M> {
193207
}
194208

195209
/// Fetch a single window from the manager.
196-
fn get_window(&self, label: &M::Label) -> Option<Window<M>> {
210+
fn get_window<L>(&self, label: &L) -> Option<Window<P>>
211+
where
212+
L: TagRef<P::Label> + ?Sized,
213+
P::Label: Borrow<L>,
214+
{
197215
self.manager().get_window(label)
198216
}
199217

200218
/// Fetch all managed windows.
201-
fn windows(&self) -> HashMap<M::Label, Window<M>> {
219+
fn windows(&self) -> HashMap<P::Label, Window<P>> {
202220
self.manager().windows()
203221
}
204222
}

core/tauri/src/runtime/app.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ impl<M: Params> App<M> {
7474
// invoke the Event `tauri://update` from JS or rust side.
7575
main_window.listen(
7676
updater::EVENT_CHECK_UPDATE
77-
.parse()
77+
.parse::<M::Event>()
7878
.unwrap_or_else(|_| panic!("bad label")),
7979
move |_msg| {
8080
let window = event_window.clone();

core/tauri/src/runtime/manager.rs

Lines changed: 50 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// SPDX-License-Identifier: Apache-2.0
33
// SPDX-License-Identifier: MIT
44

5+
use crate::runtime::tag::TagRef;
56
use crate::{
67
api::{
78
assets::Assets,
@@ -13,7 +14,7 @@ use crate::{
1314
hooks::{InvokeHandler, InvokeMessage, InvokePayload, OnPageLoad, PageLoadPayload},
1415
plugin::PluginStore,
1516
runtime::{
16-
tag::{tags_to_javascript_array, Tag, ToJavascript},
17+
tag::{tags_to_javascript_array, Tag, ToJsString},
1718
webview::{Attributes, CustomProtocol, FileDropEvent, FileDropHandler, WebviewRpcHandler},
1819
window::{DetachedWindow, PendingWindow},
1920
Dispatch, Icon, Runtime,
@@ -23,6 +24,7 @@ use crate::{
2324
};
2425
use serde::Serialize;
2526
use serde_json::Value as JsonValue;
27+
use std::borrow::Borrow;
2628
use std::marker::PhantomData;
2729
use std::{
2830
borrow::Cow,
@@ -33,6 +35,20 @@ use std::{
3335
};
3436
use uuid::Uuid;
3537

38+
/// Parse a string representing an internal tauri event into [`Params::Event`]
39+
///
40+
/// # Panics
41+
///
42+
/// This will panic if the `FromStr` implementation of [`Params::Event`] returns an error.
43+
pub(crate) fn tauri_event<Event: Tag>(tauri_event: &str) -> Event {
44+
tauri_event.parse().unwrap_or_else(|_| {
45+
panic!(
46+
"failed to parse internal tauri event into Params::Event: {}",
47+
tauri_event
48+
)
49+
})
50+
}
51+
3652
pub struct InnerWindowManager<P: Params> {
3753
windows: Mutex<HashMap<P::Label, Window<P>>>,
3854
plugins: Mutex<PluginStore<P>>,
@@ -168,7 +184,7 @@ impl<P: Params> WindowManager<P> {
168184
window.__TAURI__.__currentWindow = {{ label: {current_window_label} }}
169185
"#,
170186
window_labels_array = tags_to_javascript_array(pending_labels)?,
171-
current_window_label = label.to_javascript()?,
187+
current_window_label = label.to_js_string()?,
172188
));
173189

174190
if !attributes.has_icon() {
@@ -281,14 +297,16 @@ impl<P: Params> WindowManager<P> {
281297
let window = manager.attach_window(window);
282298
let _ = match event {
283299
FileDropEvent::Hovered(paths) => {
284-
window.emit_internal("tauri://file-drop".to_string(), Some(paths))
285-
}
286-
FileDropEvent::Dropped(paths) => {
287-
window.emit_internal("tauri://file-drop-hover".to_string(), Some(paths))
288-
}
289-
FileDropEvent::Cancelled => {
290-
window.emit_internal("tauri://file-drop-cancelled".to_string(), Some(()))
300+
window.emit_internal(&tauri_event::<P::Event>("tauri://file-drop"), Some(paths))
291301
}
302+
FileDropEvent::Dropped(paths) => window.emit_internal(
303+
&tauri_event::<P::Event>("tauri://file-drop-hover"),
304+
Some(paths),
305+
),
306+
FileDropEvent::Cancelled => window.emit_internal(
307+
&tauri_event::<P::Event>("tauri://file-drop-cancelled"),
308+
Some(()),
309+
),
292310
};
293311
});
294312
true
@@ -474,30 +492,20 @@ impl<P: Params> WindowManager<P> {
474492

475493
window
476494
}
477-
pub fn emit_filter_internal<S: Serialize + Clone, F: Fn(&Window<P>) -> bool>(
478-
&self,
479-
event: String,
480-
payload: Option<S>,
481-
filter: F,
482-
) -> crate::Result<()> {
483-
self
484-
.windows_lock()
485-
.values()
486-
.filter(|&w| filter(w))
487-
.try_for_each(|window| window.emit_internal(event.clone(), payload.clone()))
488-
}
489-
pub fn emit_filter<S: Serialize + Clone, F: Fn(&Window<P>) -> bool>(
490-
&self,
491-
event: P::Event,
492-
payload: Option<S>,
493-
filter: F,
494-
) -> crate::Result<()> {
495+
496+
pub fn emit_filter<E, S, F>(&self, event: &E, payload: Option<S>, filter: F) -> crate::Result<()>
497+
where
498+
E: TagRef<P::Event> + ?Sized,
499+
S: Serialize + Clone,
500+
F: Fn(&Window<P>) -> bool,
501+
{
495502
self
496503
.windows_lock()
497504
.values()
498505
.filter(|&w| filter(w))
499-
.try_for_each(|window| window.emit(&event, payload.clone()))
506+
.try_for_each(|window| window.emit(event, payload.clone()))
500507
}
508+
501509
pub fn labels(&self) -> HashSet<P::Label> {
502510
self.windows_lock().keys().cloned().collect()
503511
}
@@ -510,9 +518,15 @@ impl<P: Params> WindowManager<P> {
510518
pub fn unlisten(&self, handler_id: EventHandler) {
511519
self.inner.listeners.unlisten(handler_id)
512520
}
513-
pub fn trigger(&self, event: P::Event, window: Option<P::Label>, data: Option<String>) {
521+
522+
pub fn trigger<E>(&self, event: &E, window: Option<P::Label>, data: Option<String>)
523+
where
524+
E: TagRef<P::Event> + ?Sized,
525+
P::Event: Borrow<E>,
526+
{
514527
self.inner.listeners.trigger(event, window, data)
515528
}
529+
516530
pub fn listen<F: Fn(Event) + Send + 'static>(
517531
&self,
518532
event: P::Event,
@@ -563,9 +577,15 @@ impl<P: Params> WindowManager<P> {
563577
.expect("poisoned salt mutex")
564578
.remove(&uuid)
565579
}
566-
pub fn get_window(&self, label: &P::Label) -> Option<Window<P>> {
580+
581+
pub fn get_window<L>(&self, label: &L) -> Option<Window<P>>
582+
where
583+
L: TagRef<P::Label> + ?Sized,
584+
P::Label: Borrow<L>,
585+
{
567586
self.windows_lock().get(label).cloned()
568587
}
588+
569589
pub fn windows(&self) -> HashMap<P::Label, Window<P>> {
570590
self.windows_lock().clone()
571591
}

0 commit comments

Comments
 (0)