// Copyright 2019-2024 Tauri Programme within The Commons Conservancy // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT /** * The event system allows you to emit events to the backend and listen to events from it. * * This package is also accessible with `window.__TAURI__.event` when [`app.withGlobalTauri`](https://tauri.app/v1/api/config/#appconfig.withglobaltauri) in `tauri.conf.json` is set to `true`. * @module */ import { invoke, transformCallback } from './core' type EventTarget = | { kind: 'Any' } | { kind: 'AnyLabel'; label: string } | { kind: 'App' } | { kind: 'Window'; label: string } | { kind: 'Webview'; label: string } | { kind: 'WebviewWindow'; label: string } interface Event { /** Event name */ event: EventName /** Event identifier used to unlisten */ id: number /** Event payload */ payload: T } type EventCallback = (event: Event) => void type UnlistenFn = () => void type EventName = `${TauriEvent}` | (string & Record) interface Options { /** * The event target to listen to, defaults to `{ kind: 'Any' }`, see {@link EventTarget}. * * If a string is provided, {@link EventTarget.AnyLabel} is used. */ target?: string | EventTarget } /** * @since 1.1.0 */ enum TauriEvent { WINDOW_RESIZED = 'tauri://resize', WINDOW_MOVED = 'tauri://move', WINDOW_CLOSE_REQUESTED = 'tauri://close-requested', WINDOW_DESTROYED = 'tauri://destroyed', WINDOW_FOCUS = 'tauri://focus', WINDOW_BLUR = 'tauri://blur', WINDOW_SCALE_FACTOR_CHANGED = 'tauri://scale-change', WINDOW_THEME_CHANGED = 'tauri://theme-changed', WEBVIEW_CREATED = 'tauri://webview-created', FILE_DROP = 'tauri://file-drop', FILE_DROP_HOVER = 'tauri://file-drop-hover', FILE_DROP_CANCELLED = 'tauri://file-drop-cancelled' } /** * Unregister the event listener associated with the given name and id. * * @ignore * @param event The event name * @param eventId Event identifier * @returns */ async function _unlisten(event: string, eventId: number): Promise { await invoke('plugin:event|unlisten', { event, eventId }) } /** * Listen to an emitted event to any {@link EventTarget|target}. * * @example * ```typescript * import { listen } from '@tauri-apps/api/event'; * const unlisten = await listen('error', (event) => { * console.log(`Got error, payload: ${event.payload}`); * }); * * // 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. * @param options Event listening options. * @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. * * @since 1.0.0 */ async function listen( event: EventName, handler: EventCallback, options?: Options ): Promise { const target: EventTarget = typeof options?.target === 'string' ? { kind: 'AnyLabel', label: options.target } : options?.target ?? { kind: 'Any' } return invoke('plugin:event|listen', { event, target, handler: transformCallback(handler) }).then((eventId) => { return async () => _unlisten(event, eventId) }) } /** * Listens once to an emitted event to any {@link EventTarget|target}. * * @example * ```typescript * import { once } from '@tauri-apps/api/event'; * interface LoadedPayload { * loggedIn: boolean, * token: string * } * const unlisten = await once('loaded', (event) => { * console.log(`App is loaded, loggedIn: ${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. * @param options Event listening options. * @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. * * @since 1.0.0 */ async function once( event: EventName, handler: EventCallback, options?: Options ): Promise { return listen( event, (eventData) => { handler(eventData) _unlisten(event, eventData.id).catch(() => {}) }, options ) } /** * Emits an event to all {@link EventTarget|targets}. * * @example * ```typescript * import { emit } from '@tauri-apps/api/event'; * await emit('frontend-loaded', { loggedIn: true, token: 'authToken' }); * ``` * * @param event Event name. Must include only alphanumeric characters, `-`, `/`, `:` and `_`. * @param payload Event payload. * * @since 1.0.0 */ async function emit(event: string, payload?: unknown): Promise { await invoke('plugin:event|emit', { event, payload }) } /** * Emits an event to all {@link EventTarget|targets} matching the given target. * * @example * ```typescript * import { emitTo } from '@tauri-apps/api/event'; * await emitTo('main', 'frontend-loaded', { loggedIn: true, token: 'authToken' }); * ``` * * @param target Label of the target Window/Webview/WebviewWindow or raw {@link EventTarget} object. * @param event Event name. Must include only alphanumeric characters, `-`, `/`, `:` and `_`. * @param payload Event payload. * * @since 1.0.0 */ async function emitTo( target: EventTarget | string, event: string, payload?: unknown ): Promise { const eventTarget: EventTarget = typeof target === 'string' ? { kind: 'AnyLabel', label: target } : target await invoke('plugin:event|emit_to', { target: eventTarget, event, payload }) } export type { Event, EventTarget, EventCallback, UnlistenFn, EventName, Options } export { listen, once, emit, emitTo, TauriEvent }