Skip to content

Commit

Permalink
feat(api): add abstractions to updater and window event listeners (#4569
Browse files Browse the repository at this point in the history
)
  • Loading branch information
lucasfernog committed Jul 5, 2022
1 parent e29fff2 commit b02fc90
Show file tree
Hide file tree
Showing 9 changed files with 431 additions and 147 deletions.
5 changes: 5 additions & 0 deletions .changes/api-event-listeners.md
@@ -0,0 +1,5 @@
---
"api": patch
---

Added helper functions to listen to updater and window events.
2 changes: 1 addition & 1 deletion core/tauri/scripts/bundle.js

Large diffs are not rendered by default.

70 changes: 35 additions & 35 deletions examples/api/dist/assets/index.js

Large diffs are not rendered by default.

39 changes: 21 additions & 18 deletions examples/api/src-tauri/src/main.rs
Expand Up @@ -214,24 +214,27 @@ fn main() {
event: WindowEvent::CloseRequested { api, .. },
..
} => {
let app_handle = app_handle.clone();
let window = app_handle.get_window(&label).unwrap();
// use the exposed close api, and prevent the event loop to close
api.prevent_close();
// ask the user if he wants to quit
ask(
Some(&window),
"Tauri API",
"Are you sure that you want to close this window?",
move |answer| {
if answer {
// .close() cannot be called on the main thread
std::thread::spawn(move || {
app_handle.get_window(&label).unwrap().close().unwrap();
});
}
},
);
// for other windows, we handle it in JS
if label == "main" {
let app_handle = app_handle.clone();
let window = app_handle.get_window(&label).unwrap();
// use the exposed close api, and prevent the event loop to close
api.prevent_close();
// ask the user if he wants to quit
ask(
Some(&window),
"Tauri API",
"Are you sure that you want to close this window?",
move |answer| {
if answer {
// .close() cannot be called on the main thread
std::thread::spawn(move || {
app_handle.get_window(&label).unwrap().close().unwrap();
});
}
},
);
}
}

// Keep the event loop running even if all windows are closed
Expand Down
14 changes: 12 additions & 2 deletions examples/api/src/App.svelte
Expand Up @@ -22,8 +22,18 @@
import { listen } from '@tauri-apps/api/event'
import { ask } from '@tauri-apps/api/dialog'
appWindow.listen('tauri://file-drop', function (event) {
onMessage(`File drop: ${event.payload}`)
if (appWindow.label !== 'main') {
appWindow.onCloseRequested(async (event) => {
const confirmed = await confirm('Are you sure?')
if (!confirmed) {
// user did not confirm closing the window; let's prevent it
event.preventDefault()
}
})
}
appWindow.onFileDropEvent((event) => {
onMessage(`File drop: ${JSON.stringify(event.payload)}`)
})
const views = [
Expand Down
11 changes: 9 additions & 2 deletions tooling/api/src/event.ts
Expand Up @@ -19,20 +19,22 @@ import type {

/**
* Listen to an event from the backend.
*
* @example
* ```typescript
* import { listen } from '@tauri-apps/api/event';
* const unlisten = await listen<string>('error', (event) => {
* console.log(`Got error in window ${event.windowLabel}, payload: ${payload}`);
* });
*
* // removes the listener later
* await unlisten();
* // you need to call unlisten if your handler goes out of scope e.g. the component is unmounted
* unlisten();
* ```
*
* @param event Event name. Must include only alphanumeric characters, `-`, `/`, `:` and `_`.
* @param handler Event handler callback.
* @return A promise resolving to a function to unlisten to the event.
* Note that removing the listener is required if your listener goes out of scope e.g. the component is unmounted.
*/
async function listen<T>(
event: EventName,
Expand All @@ -43,6 +45,7 @@ async function listen<T>(

/**
* Listen to an one-off event from the backend.
*
* @example
* ```typescript
* import { once } from '@tauri-apps/api/event';
Expand All @@ -53,11 +56,15 @@ async function listen<T>(
* const unlisten = await once<LoadedPayload>('loaded', (event) => {
* console.log(`App is loaded, logggedIn: ${event.payload.loggedIn}, token: ${event.payload.token}`);
* });
*
* // you need to call unlisten if your handler goes out of scope e.g. the component is unmounted
* unlisten();
* ```
*
* @param event Event name. Must include only alphanumeric characters, `-`, `/`, `:` and `_`.
* @param handler Event handler callback.
* @returns A promise resolving to a function to unlisten to the event.
* Note that removing the listener is required if your listener goes out of scope e.g. the component is unmounted.
*/
async function once<T>(
event: EventName,
Expand Down
21 changes: 1 addition & 20 deletions tooling/api/src/helpers/event.ts
Expand Up @@ -5,7 +5,6 @@
import { WindowLabel } from '../window'
import { invokeTauriCommand } from './tauri'
import { transformCallback } from '../tauri'
import { LiteralUnion } from 'type-fest'

export interface Event<T> {
/** Event name */
Expand All @@ -18,25 +17,7 @@ export interface Event<T> {
payload: T
}

export type EventName = LiteralUnion<
| 'tauri://update'
| 'tauri://update-available'
| 'tauri://update-download-progress'
| 'tauri://update-install'
| 'tauri://update-status'
| 'tauri://resize'
| 'tauri://move'
| 'tauri://close-requested'
| 'tauri://focus'
| 'tauri://blur'
| 'tauri://scale-change'
| 'tauri://menu'
| 'tauri://file-drop'
| 'tauri://file-drop-hover'
| 'tauri://file-drop-cancelled'
| 'tauri://theme-changed',
string
>
export type EventName = string

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

Expand Down
35 changes: 28 additions & 7 deletions tooling/api/src/updater.ts
Expand Up @@ -29,6 +29,31 @@ interface UpdateResult {
shouldUpdate: boolean
}

/**
* Listen to an updater event.
* @example
* ```typescript
* import { onUpdaterEvent } from "@tauri-apps/api/updater";
* const unlisten = await onUpdaterEvent(({ error, status }) => {
* console.log('Updater event', error, status);
* });
*
* // you need to call unlisten if your handler goes out of scope e.g. the component is unmounted
* unlisten();
* ```
*
* @param handler
* @returns A promise resolving to a function to unlisten to the event.
* Note that removing the listener is required if your listener goes out of scope e.g. the component is unmounted.
*/
async function onUpdaterEvent(
handler: (status: UpdateStatusResult) => void
): Promise<UnlistenFn> {
return listen('tauri://update-status', (data: { payload: any }) => {
handler(data?.payload as UpdateStatusResult)
})
}

/**
* Install the update if there's one available.
* @example
Expand Down Expand Up @@ -68,9 +93,7 @@ async function installUpdate(): Promise<void> {
}

// listen status change
listen('tauri://update-status', (data: { payload: any }) => {
onStatusChange(data?.payload as UpdateStatusResult)
})
onUpdaterEvent(onStatusChange)
.then((fn) => {
unlistenerFn = fn
})
Expand Down Expand Up @@ -144,9 +167,7 @@ async function checkUpdate(): Promise<UpdateResult> {
})

// listen status change
listen('tauri://update-status', (data: { payload: any }) => {
onStatusChange(data?.payload as UpdateStatusResult)
})
onUpdaterEvent(onStatusChange)
.then((fn) => {
unlistenerFn = fn
})
Expand All @@ -167,4 +188,4 @@ async function checkUpdate(): Promise<UpdateResult> {

export type { UpdateStatus, UpdateStatusResult, UpdateManifest, UpdateResult }

export { installUpdate, checkUpdate }
export { onUpdaterEvent, installUpdate, checkUpdate }

0 comments on commit b02fc90

Please sign in to comment.