mirror of
https://github.com/tauri-apps/tauri.git
synced 2024-08-16 19:30:27 +03:00
fix(core): fix emit skipping webview listeners if filter wasn't provided (#9107)
* fix(core): fix emit skipping webview listeners if filter wasn't provided * Update .changes/core-emit-js-all-targets.md * update api example --------- Co-authored-by: Lucas Fernandes Nogueira <lucas@tauri.app> Co-authored-by: Lucas Nogueira <lucas@tauri.studio>
This commit is contained in:
parent
80c12ead46
commit
5541aafef3
5
.changes/core-emit-js-all-targets.md
Normal file
5
.changes/core-emit-js-all-targets.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
'tauri': 'patch:bug'
|
||||
---
|
||||
|
||||
Fix `emit` and `emit_to` (when used with `EventTarget::Any`) always skipping the webview listeners.
|
@ -16,12 +16,6 @@ use std::{
|
||||
},
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
struct JsHandler {
|
||||
target: EventTarget,
|
||||
id: EventId,
|
||||
}
|
||||
|
||||
/// What to do with the pending handler when resolving it?
|
||||
enum Pending {
|
||||
Unlisten(EventId),
|
||||
@ -48,6 +42,18 @@ impl Handler {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
struct JsHandler {
|
||||
target: EventTarget,
|
||||
id: EventId,
|
||||
}
|
||||
|
||||
impl JsHandler {
|
||||
fn new(target: EventTarget, id: EventId) -> Self {
|
||||
Self { target, id }
|
||||
}
|
||||
}
|
||||
|
||||
type WebviewLabel = String;
|
||||
type EventName = String;
|
||||
|
||||
@ -189,27 +195,20 @@ impl Listeners {
|
||||
F: Fn(&EventTarget) -> bool,
|
||||
{
|
||||
let mut maybe_pending = false;
|
||||
|
||||
match self.inner.handlers.try_lock() {
|
||||
Err(_) => self.insert_pending(Pending::Emit(emit_args.clone())),
|
||||
Ok(lock) => {
|
||||
if let Some(handlers) = lock.get(&emit_args.event_name) {
|
||||
let handlers: Vec<_> = match filter {
|
||||
Some(filter) => handlers
|
||||
.iter()
|
||||
.filter(|(_, Handler { target, .. })| *target == EventTarget::Any || filter(target))
|
||||
.collect(),
|
||||
None => handlers.iter().collect(),
|
||||
};
|
||||
|
||||
if !handlers.is_empty() {
|
||||
maybe_pending = true;
|
||||
let handlers = handlers.iter();
|
||||
let handlers = handlers.filter(|(_, h)| match_any_or_filter(&h.target, &filter));
|
||||
for (&id, Handler { callback, .. }) in handlers {
|
||||
maybe_pending = true;
|
||||
(callback)(Event::new(id, emit_args.payload.clone()))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if maybe_pending {
|
||||
self.flush_pending()?;
|
||||
@ -236,44 +235,26 @@ impl Listeners {
|
||||
.or_default()
|
||||
.entry(event.to_string())
|
||||
.or_default()
|
||||
.insert(JsHandler { id, target });
|
||||
.insert(JsHandler::new(target, id));
|
||||
}
|
||||
|
||||
pub(crate) fn unlisten_js(&self, id: EventId) {
|
||||
let mut listeners = self.inner.js_event_listeners.lock().unwrap();
|
||||
|
||||
let mut empty = None;
|
||||
let listeners = listeners.values_mut();
|
||||
'outer: for listeners in listeners {
|
||||
for (key, handlers) in listeners.iter_mut() {
|
||||
let mut found = false;
|
||||
|
||||
handlers.retain(|h| {
|
||||
let keep = h.id != id;
|
||||
if !found {
|
||||
found = !keep
|
||||
}
|
||||
keep
|
||||
});
|
||||
pub(crate) fn unlisten_js(&self, event: &str, id: EventId) {
|
||||
let mut js_listeners = self.inner.js_event_listeners.lock().unwrap();
|
||||
let js_listeners = js_listeners.values_mut();
|
||||
for js_listeners in js_listeners {
|
||||
if let Some(handlers) = js_listeners.get_mut(event) {
|
||||
handlers.retain(|h| h.id != id);
|
||||
|
||||
if handlers.is_empty() {
|
||||
empty.replace(key.clone());
|
||||
js_listeners.remove(event);
|
||||
}
|
||||
|
||||
if found {
|
||||
break 'outer;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(key) = &empty {
|
||||
listeners.remove(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn unlisten_all_js(&self, webview_label: &str) {
|
||||
let inner_listeners = self.inner.as_ref();
|
||||
let mut js_listeners = inner_listeners.js_event_listeners.lock().unwrap();
|
||||
let js_listeners = self.inner.as_ref();
|
||||
let mut js_listeners = js_listeners.js_event_listeners.lock().unwrap();
|
||||
js_listeners.remove(webview_label);
|
||||
}
|
||||
|
||||
@ -282,11 +263,11 @@ impl Listeners {
|
||||
event: &str,
|
||||
filter: F,
|
||||
) -> bool {
|
||||
let listeners = self.inner.js_event_listeners.lock().unwrap();
|
||||
listeners.values().any(|events| {
|
||||
let js_listeners = self.inner.js_event_listeners.lock().unwrap();
|
||||
js_listeners.values().any(|events| {
|
||||
events
|
||||
.get(event)
|
||||
.map(|handlers| handlers.iter().any(|h| filter(&h.target)))
|
||||
.map(|handlers| handlers.iter().any(|handler| filter(&handler.target)))
|
||||
.unwrap_or(false)
|
||||
})
|
||||
}
|
||||
@ -296,22 +277,22 @@ impl Listeners {
|
||||
mut webviews: I,
|
||||
event: &str,
|
||||
emit_args: &EmitArgs,
|
||||
filter: Option<&F>,
|
||||
filter: Option<F>,
|
||||
) -> crate::Result<()>
|
||||
where
|
||||
R: Runtime,
|
||||
I: Iterator<Item = &'a Webview<R>>,
|
||||
F: Fn(&EventTarget) -> bool,
|
||||
{
|
||||
let listeners = self.inner.js_event_listeners.lock().unwrap();
|
||||
let js_listeners = self.inner.js_event_listeners.lock().unwrap();
|
||||
webviews.try_for_each(|webview| {
|
||||
if let Some(handlers) = listeners.get(webview.label()).and_then(|s| s.get(event)) {
|
||||
if let Some(handlers) = js_listeners.get(webview.label()).and_then(|s| s.get(event)) {
|
||||
let handlers = handlers.iter();
|
||||
let handlers = handlers.filter(|handler| match_any_or_filter(&handler.target, &filter));
|
||||
for JsHandler { target, .. } in handlers {
|
||||
if *target == EventTarget::Any || filter.as_ref().map(|f| f(target)).unwrap_or(false) {
|
||||
webview.emit_js(emit_args, target)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
})
|
||||
@ -331,11 +312,19 @@ impl Listeners {
|
||||
webviews,
|
||||
event,
|
||||
emit_args,
|
||||
None::<&&dyn Fn(&EventTarget) -> bool>,
|
||||
None::<&dyn Fn(&EventTarget) -> bool>,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn match_any_or_filter<F: Fn(&EventTarget) -> bool>(
|
||||
target: &EventTarget,
|
||||
filter: &Option<F>,
|
||||
) -> bool {
|
||||
*target == EventTarget::Any || filter.as_ref().map(|f| f(target)).unwrap_or(true)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
@ -1297,7 +1297,7 @@ fn main() {
|
||||
id,
|
||||
))?;
|
||||
|
||||
listeners.unlisten_js(id);
|
||||
listeners.unlisten_js(event, id);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
38
examples/api/src-tauri/Cargo.lock
generated
38
examples/api/src-tauri/Cargo.lock
generated
@ -172,6 +172,12 @@ version = "0.21.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567"
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.22.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9475866fec1451be56a3c2400fd081ff546538961565ccb5b7142cbd22bc7a51"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
@ -1769,9 +1775,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.20"
|
||||
version = "0.4.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
|
||||
checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
|
||||
|
||||
[[package]]
|
||||
name = "loom"
|
||||
@ -2265,7 +2271,7 @@ version = "1.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5699cc8a63d1aa2b1ee8e12b9ad70ac790d65788cd36101fa37f87ea46c4cef"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"base64 0.21.7",
|
||||
"indexmap 2.2.3",
|
||||
"line-wrap",
|
||||
"quick-xml",
|
||||
@ -2556,7 +2562,7 @@ version = "0.11.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c6920094eb85afde5e4a138be3f2de8bbdf28000f0029e72c45025a56b042251"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"base64 0.21.7",
|
||||
"bytes",
|
||||
"encoding_rs",
|
||||
"futures-core",
|
||||
@ -2790,7 +2796,7 @@ version = "3.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "15d167997bd841ec232f5b2b8e0e26606df2e7caa4c31b95ea9ca52b200bd270"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"base64 0.21.7",
|
||||
"chrono",
|
||||
"hex",
|
||||
"indexmap 1.9.3",
|
||||
@ -3019,7 +3025,7 @@ version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1bbdb58577b6301f8d17ae2561f32002a5bae056d444e0f69e611e504a276204"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"base64 0.21.7",
|
||||
"serde",
|
||||
"serde_json",
|
||||
]
|
||||
@ -3145,7 +3151,7 @@ checksum = "e1fc403891a21bcfb7c37834ba66a547a8f402146eba7265b5a6d88059c9ff2f"
|
||||
|
||||
[[package]]
|
||||
name = "tauri"
|
||||
version = "2.0.0-beta.8"
|
||||
version = "2.0.0-beta.9"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bytes",
|
||||
@ -3195,7 +3201,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tauri-build"
|
||||
version = "2.0.0-beta.6"
|
||||
version = "2.0.0-beta.7"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cargo_toml",
|
||||
@ -3217,9 +3223,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tauri-codegen"
|
||||
version = "2.0.0-beta.6"
|
||||
version = "2.0.0-beta.7"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"base64 0.22.0",
|
||||
"brotli",
|
||||
"ico",
|
||||
"json-patch",
|
||||
@ -3242,7 +3248,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tauri-macros"
|
||||
version = "2.0.0-beta.6"
|
||||
version = "2.0.0-beta.7"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
@ -3254,7 +3260,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tauri-plugin"
|
||||
version = "2.0.0-beta.6"
|
||||
version = "2.0.0-beta.7"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"glob",
|
||||
@ -3280,7 +3286,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tauri-runtime"
|
||||
version = "2.0.0-beta.6"
|
||||
version = "2.0.0-beta.7"
|
||||
dependencies = [
|
||||
"gtk",
|
||||
"http",
|
||||
@ -3296,7 +3302,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tauri-runtime-wry"
|
||||
version = "2.0.0-beta.6"
|
||||
version = "2.0.0-beta.7"
|
||||
dependencies = [
|
||||
"cocoa",
|
||||
"gtk",
|
||||
@ -3318,7 +3324,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tauri-utils"
|
||||
version = "2.0.0-beta.6"
|
||||
version = "2.0.0-beta.7"
|
||||
dependencies = [
|
||||
"aes-gcm",
|
||||
"brotli",
|
||||
@ -4384,7 +4390,7 @@ version = "0.37.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b717040ba9771fd88eb428c6ea6b555f8e734ff8534f02c13e8f10d97f5935e"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"base64 0.21.7",
|
||||
"block",
|
||||
"cfg_aliases 0.1.1",
|
||||
"cocoa",
|
||||
|
@ -1,13 +1,15 @@
|
||||
<script>
|
||||
import { listen, emit } from '@tauri-apps/api/event'
|
||||
import { getCurrent } from '@tauri-apps/api/webviewWindow'
|
||||
import { invoke } from '@tauri-apps/api/core'
|
||||
import { onMount, onDestroy } from 'svelte'
|
||||
|
||||
export let onMessage
|
||||
let unlisten
|
||||
|
||||
const webviewWindow = getCurrent()
|
||||
|
||||
onMount(async () => {
|
||||
unlisten = await listen('rust-event', onMessage)
|
||||
unlisten = await webviewWindow.listen('rust-event', onMessage)
|
||||
})
|
||||
onDestroy(() => {
|
||||
if (unlisten) {
|
||||
@ -35,7 +37,7 @@
|
||||
}
|
||||
|
||||
function emitEvent() {
|
||||
emit('js-event', 'this is the payload string')
|
||||
webviewWindow.emit('js-event', 'this is the payload string')
|
||||
}
|
||||
</script>
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user