Skip to content

Commit b02fc90

Browse files
authored
feat(api): add abstractions to updater and window event listeners (#4569)
1 parent e29fff2 commit b02fc90

File tree

9 files changed

+431
-147
lines changed

9 files changed

+431
-147
lines changed

.changes/api-event-listeners.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"api": patch
3+
---
4+
5+
Added helper functions to listen to updater and window events.

core/tauri/scripts/bundle.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.

examples/api/dist/assets/index.js

Lines changed: 35 additions & 35 deletions
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: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -214,24 +214,27 @@ fn main() {
214214
event: WindowEvent::CloseRequested { api, .. },
215215
..
216216
} => {
217-
let app_handle = app_handle.clone();
218-
let window = app_handle.get_window(&label).unwrap();
219-
// use the exposed close api, and prevent the event loop to close
220-
api.prevent_close();
221-
// ask the user if he wants to quit
222-
ask(
223-
Some(&window),
224-
"Tauri API",
225-
"Are you sure that you want to close this window?",
226-
move |answer| {
227-
if answer {
228-
// .close() cannot be called on the main thread
229-
std::thread::spawn(move || {
230-
app_handle.get_window(&label).unwrap().close().unwrap();
231-
});
232-
}
233-
},
234-
);
217+
// for other windows, we handle it in JS
218+
if label == "main" {
219+
let app_handle = app_handle.clone();
220+
let window = app_handle.get_window(&label).unwrap();
221+
// use the exposed close api, and prevent the event loop to close
222+
api.prevent_close();
223+
// ask the user if he wants to quit
224+
ask(
225+
Some(&window),
226+
"Tauri API",
227+
"Are you sure that you want to close this window?",
228+
move |answer| {
229+
if answer {
230+
// .close() cannot be called on the main thread
231+
std::thread::spawn(move || {
232+
app_handle.get_window(&label).unwrap().close().unwrap();
233+
});
234+
}
235+
},
236+
);
237+
}
235238
}
236239

237240
// Keep the event loop running even if all windows are closed

examples/api/src/App.svelte

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,18 @@
2222
import { listen } from '@tauri-apps/api/event'
2323
import { ask } from '@tauri-apps/api/dialog'
2424
25-
appWindow.listen('tauri://file-drop', function (event) {
26-
onMessage(`File drop: ${event.payload}`)
25+
if (appWindow.label !== 'main') {
26+
appWindow.onCloseRequested(async (event) => {
27+
const confirmed = await confirm('Are you sure?')
28+
if (!confirmed) {
29+
// user did not confirm closing the window; let's prevent it
30+
event.preventDefault()
31+
}
32+
})
33+
}
34+
35+
appWindow.onFileDropEvent((event) => {
36+
onMessage(`File drop: ${JSON.stringify(event.payload)}`)
2737
})
2838
2939
const views = [

tooling/api/src/event.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,20 +19,22 @@ import type {
1919

2020
/**
2121
* Listen to an event from the backend.
22+
*
2223
* @example
2324
* ```typescript
2425
* import { listen } from '@tauri-apps/api/event';
2526
* const unlisten = await listen<string>('error', (event) => {
2627
* console.log(`Got error in window ${event.windowLabel}, payload: ${payload}`);
2728
* });
2829
*
29-
* // removes the listener later
30-
* await unlisten();
30+
* // you need to call unlisten if your handler goes out of scope e.g. the component is unmounted
31+
* unlisten();
3132
* ```
3233
*
3334
* @param event Event name. Must include only alphanumeric characters, `-`, `/`, `:` and `_`.
3435
* @param handler Event handler callback.
3536
* @return A promise resolving to a function to unlisten to the event.
37+
* Note that removing the listener is required if your listener goes out of scope e.g. the component is unmounted.
3638
*/
3739
async function listen<T>(
3840
event: EventName,
@@ -43,6 +45,7 @@ async function listen<T>(
4345

4446
/**
4547
* Listen to an one-off event from the backend.
48+
*
4649
* @example
4750
* ```typescript
4851
* import { once } from '@tauri-apps/api/event';
@@ -53,11 +56,15 @@ async function listen<T>(
5356
* const unlisten = await once<LoadedPayload>('loaded', (event) => {
5457
* console.log(`App is loaded, logggedIn: ${event.payload.loggedIn}, token: ${event.payload.token}`);
5558
* });
59+
*
60+
* // you need to call unlisten if your handler goes out of scope e.g. the component is unmounted
61+
* unlisten();
5662
* ```
5763
*
5864
* @param event Event name. Must include only alphanumeric characters, `-`, `/`, `:` and `_`.
5965
* @param handler Event handler callback.
6066
* @returns A promise resolving to a function to unlisten to the event.
67+
* Note that removing the listener is required if your listener goes out of scope e.g. the component is unmounted.
6168
*/
6269
async function once<T>(
6370
event: EventName,

tooling/api/src/helpers/event.ts

Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
import { WindowLabel } from '../window'
66
import { invokeTauriCommand } from './tauri'
77
import { transformCallback } from '../tauri'
8-
import { LiteralUnion } from 'type-fest'
98

109
export interface Event<T> {
1110
/** Event name */
@@ -18,25 +17,7 @@ export interface Event<T> {
1817
payload: T
1918
}
2019

21-
export type EventName = LiteralUnion<
22-
| 'tauri://update'
23-
| 'tauri://update-available'
24-
| 'tauri://update-download-progress'
25-
| 'tauri://update-install'
26-
| 'tauri://update-status'
27-
| 'tauri://resize'
28-
| 'tauri://move'
29-
| 'tauri://close-requested'
30-
| 'tauri://focus'
31-
| 'tauri://blur'
32-
| 'tauri://scale-change'
33-
| 'tauri://menu'
34-
| 'tauri://file-drop'
35-
| 'tauri://file-drop-hover'
36-
| 'tauri://file-drop-cancelled'
37-
| 'tauri://theme-changed',
38-
string
39-
>
20+
export type EventName = string
4021

4122
export type EventCallback<T> = (event: Event<T>) => void
4223

tooling/api/src/updater.ts

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,31 @@ interface UpdateResult {
2929
shouldUpdate: boolean
3030
}
3131

32+
/**
33+
* Listen to an updater event.
34+
* @example
35+
* ```typescript
36+
* import { onUpdaterEvent } from "@tauri-apps/api/updater";
37+
* const unlisten = await onUpdaterEvent(({ error, status }) => {
38+
* console.log('Updater event', error, status);
39+
* });
40+
*
41+
* // you need to call unlisten if your handler goes out of scope e.g. the component is unmounted
42+
* unlisten();
43+
* ```
44+
*
45+
* @param handler
46+
* @returns A promise resolving to a function to unlisten to the event.
47+
* Note that removing the listener is required if your listener goes out of scope e.g. the component is unmounted.
48+
*/
49+
async function onUpdaterEvent(
50+
handler: (status: UpdateStatusResult) => void
51+
): Promise<UnlistenFn> {
52+
return listen('tauri://update-status', (data: { payload: any }) => {
53+
handler(data?.payload as UpdateStatusResult)
54+
})
55+
}
56+
3257
/**
3358
* Install the update if there's one available.
3459
* @example
@@ -68,9 +93,7 @@ async function installUpdate(): Promise<void> {
6893
}
6994

7095
// listen status change
71-
listen('tauri://update-status', (data: { payload: any }) => {
72-
onStatusChange(data?.payload as UpdateStatusResult)
73-
})
96+
onUpdaterEvent(onStatusChange)
7497
.then((fn) => {
7598
unlistenerFn = fn
7699
})
@@ -144,9 +167,7 @@ async function checkUpdate(): Promise<UpdateResult> {
144167
})
145168

146169
// listen status change
147-
listen('tauri://update-status', (data: { payload: any }) => {
148-
onStatusChange(data?.payload as UpdateStatusResult)
149-
})
170+
onUpdaterEvent(onStatusChange)
150171
.then((fn) => {
151172
unlistenerFn = fn
152173
})
@@ -167,4 +188,4 @@ async function checkUpdate(): Promise<UpdateResult> {
167188

168189
export type { UpdateStatus, UpdateStatusResult, UpdateManifest, UpdateResult }
169190

170-
export { installUpdate, checkUpdate }
191+
export { onUpdaterEvent, installUpdate, checkUpdate }

0 commit comments

Comments
 (0)