Skip to content

Commit b670ec5

Browse files
authored
refactor(core): add unlisten, once APIs to the event system (#1359)
1 parent 46f3d5f commit b670ec5

File tree

16 files changed

+228
-106
lines changed

16 files changed

+228
-106
lines changed

.changes/event-unlisten-js.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"tauri-api": minor
3+
"tauri": minor
4+
---
5+
6+
Refactor the event callback payload and return an unlisten function on the `listen` API.

.changes/event-unlisten-rust.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"tauri": minor
3+
---
4+
5+
Adds `unlisten` and `once` APIs on the Rust event system.

api/src/helpers/event.ts

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,45 @@ import { invokeTauriCommand } from './tauri'
22
import { transformCallback } from '../tauri'
33

44
export interface Event<T> {
5-
type: string
5+
/// event name.
6+
event: string
7+
/// event identifier used to unlisten.
8+
id: number
9+
/// event payload.
610
payload: T
711
}
812

913
export type EventCallback<T> = (event: Event<T>) => void
1014

15+
export type UnlistenFn = () => void
16+
1117
async function _listen<T>(
1218
event: string,
13-
handler: EventCallback<T>,
14-
once: boolean
15-
): Promise<void> {
16-
await invokeTauriCommand({
19+
handler: EventCallback<T>
20+
): Promise<UnlistenFn> {
21+
return invokeTauriCommand<number>({
1722
__tauriModule: 'Event',
1823
message: {
1924
cmd: 'listen',
2025
event,
21-
handler: transformCallback(handler, once),
22-
once
26+
handler: transformCallback(handler)
27+
}
28+
}).then((eventId) => {
29+
return async () => _unlisten(eventId)
30+
})
31+
}
32+
33+
/**
34+
* Unregister the event listener associated with the given id.
35+
*
36+
* @param {number} eventId the event identifier
37+
*/
38+
async function _unlisten(eventId: number): Promise<void> {
39+
return invokeTauriCommand({
40+
__tauriModule: 'Event',
41+
message: {
42+
cmd: 'unlisten',
43+
eventId
2344
}
2445
})
2546
}
@@ -29,12 +50,13 @@ async function _listen<T>(
2950
*
3051
* @param event the event name
3152
* @param handler the event handler callback
53+
* @return {Promise<UnlistenFn>} a promise resolving to a function to unlisten to the event.
3254
*/
3355
async function listen<T>(
3456
event: string,
3557
handler: EventCallback<T>
36-
): Promise<void> {
37-
return _listen(event, handler, false)
58+
): Promise<UnlistenFn> {
59+
return _listen(event, handler)
3860
}
3961

4062
/**
@@ -46,8 +68,11 @@ async function listen<T>(
4668
async function once<T>(
4769
event: string,
4870
handler: EventCallback<T>
49-
): Promise<void> {
50-
return _listen(event, handler, true)
71+
): Promise<UnlistenFn> {
72+
return _listen<T>(event, (eventData) => {
73+
handler(eventData)
74+
_unlisten(eventData.id).catch(() => {})
75+
})
5176
}
5277

5378
/**

api/src/window.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { invokeTauriCommand } from './helpers/tauri'
2-
import { EventCallback, emit, listen, once } from './helpers/event'
2+
import { EventCallback, UnlistenFn, emit, listen, once } from './helpers/event'
33

44
interface WindowDef {
55
label: string
@@ -39,10 +39,14 @@ class WebviewWindowHandle {
3939
*
4040
* @param event the event name
4141
* @param handler the event handler callback
42+
* @return {Promise<UnlistenFn>} a promise resolving to a function to unlisten to the event.
4243
*/
43-
async listen<T>(event: string, handler: EventCallback<T>): Promise<void> {
44+
async listen<T>(
45+
event: string,
46+
handler: EventCallback<T>
47+
): Promise<UnlistenFn> {
4448
if (this._handleTauriEvent(event, handler)) {
45-
return Promise.resolve()
49+
return Promise.resolve(() => {})
4650
}
4751
return listen(event, handler)
4852
}
@@ -70,7 +74,7 @@ class WebviewWindowHandle {
7074
if (localTauriEvents.includes(event)) {
7175
// eslint-disable-next-line
7276
for (const handler of this.listeners[event] || []) {
73-
handler({ type: event, payload })
77+
handler({ event, id: -1, payload })
7478
}
7579
return Promise.resolve()
7680
}

examples/api/public/build/bundle.js

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

examples/api/public/build/bundle.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

examples/api/src-tauri/src/main.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ fn main() {
1717
.setup(|webview_manager| async move {
1818
let dispatcher = webview_manager.current_webview().unwrap();
1919
let dispatcher_ = dispatcher.clone();
20-
dispatcher.listen("js-event", move |msg| {
21-
println!("got js-event with message '{:?}'", msg);
20+
dispatcher.listen("js-event", move |event| {
21+
println!("got js-event with message '{:?}'", event.payload());
2222
let reply = Reply {
2323
data: "something else".to_string(),
2424
};

examples/api/src/App.svelte

Lines changed: 11 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
6262
function onMessage(value) {
6363
responses += typeof value === "string" ? value : JSON.stringify(value);
64+
responses += "\n";
6465
}
6566
6667
function onLogoClick() {
@@ -72,38 +73,24 @@
7273
<div class="flex row noselect just-around" style="margin=1em;">
7374
<img src="tauri.png" height="60" on:click={onLogoClick} alt="logo" />
7475
<div>
75-
<a
76-
class="dark-link"
77-
target="_blank"
78-
href="https://tauri.studio/en/docs/getting-started/intro"
79-
>
76+
<a class="dark-link" target="_blank" href="https://tauri.studio/en/docs/getting-started/intro">
8077
Documentation
8178
</a>
82-
<a
83-
class="dark-link"
84-
target="_blank"
85-
href="https://github.com/tauri-apps/tauri"
86-
>
79+
<a class="dark-link" target="_blank" href="https://github.com/tauri-apps/tauri">
8780
Github
8881
</a>
89-
<a
90-
class="dark-link"
91-
target="_blank"
92-
href="https://github.com/tauri-apps/tauri/tree/dev/tauri/examples/api"
93-
>
82+
<a class="dark-link" target="_blank" href="https://github.com/tauri-apps/tauri/tree/dev/tauri/examples/api">
9483
Source
9584
</a>
9685
</div>
9786
</div>
9887
<div class="flex row">
9988
<div style="width:15em; margin-left:0.5em">
10089
{#each views as view}
101-
<p
102-
class="nv noselect {selected === view ? 'nv_selected' : ''}"
103-
on:click={() => select(view)}
90+
<p class="nv noselect {selected === view ? 'nv_selected' : ''}" on:click={()=> select(view)}
10491
>
105-
{view.label}
106-
</p>
92+
{view.label}
93+
</p>
10794
{/each}
10895
</div>
10996
<div class="content">
@@ -113,13 +100,10 @@
113100
<div id="response">
114101
<p class="flex row just-around">
115102
<strong>Tauri Console</strong>
116-
<a
117-
class="nv"
118-
on:click={() => {
119-
responses = [""];
120-
}}>clear</a
121-
>
103+
<a class="nv" on:click={()=> {
104+
responses = [""];
105+
}}>clear</a>
122106
</p>
123107
{responses}
124108
</div>
125-
</main>
109+
</main>

examples/api/src/components/Communication.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
55
export let onMessage;
66
7-
listen("rust-event", onMessage);
7+
listen("rust-event", onMessage)
88
99
function log() {
1010
invoke("log_operation", {

examples/multiwindow/dist/__tauri.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)