event.ts 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. // Copyright 2019-2023 Tauri Programme within The Commons Conservancy
  2. // SPDX-License-Identifier: Apache-2.0
  3. // SPDX-License-Identifier: MIT
  4. /**
  5. * The event system allows you to emit events to the backend and listen to events from it.
  6. *
  7. * This package is also accessible with `window.__TAURI__.event` when [`build.withGlobalTauri`](https://tauri.app/v1/api/config/#buildconfig.withglobaltauri) in `tauri.conf.json` is set to `true`.
  8. * @module
  9. */
  10. import { invoke, transformCallback } from './primitives'
  11. interface Event<T> {
  12. /** Event name */
  13. event: EventName
  14. /** The label of the window that emitted this event. */
  15. windowLabel: string
  16. /** Event identifier used to unlisten */
  17. id: number
  18. /** Event payload */
  19. payload: T
  20. }
  21. type EventCallback<T> = (event: Event<T>) => void
  22. type UnlistenFn = () => void
  23. type EventName = `${TauriEvent}` | (string & Record<never, never>)
  24. interface Options {
  25. /**
  26. * Label of the window the function targets.
  27. *
  28. * When listening to events and using this value,
  29. * only events triggered by the window with the given label are received.
  30. *
  31. * When emitting events, only the window with the given label will receive it.
  32. */
  33. target?: string
  34. }
  35. /**
  36. * @since 1.1.0
  37. */
  38. enum TauriEvent {
  39. WINDOW_RESIZED = 'tauri://resize',
  40. WINDOW_MOVED = 'tauri://move',
  41. WINDOW_CLOSE_REQUESTED = 'tauri://close-requested',
  42. WINDOW_CREATED = 'tauri://window-created',
  43. WINDOW_DESTROYED = 'tauri://destroyed',
  44. WINDOW_FOCUS = 'tauri://focus',
  45. WINDOW_BLUR = 'tauri://blur',
  46. WINDOW_SCALE_FACTOR_CHANGED = 'tauri://scale-change',
  47. WINDOW_THEME_CHANGED = 'tauri://theme-changed',
  48. WINDOW_FILE_DROP = 'tauri://file-drop',
  49. WINDOW_FILE_DROP_HOVER = 'tauri://file-drop-hover',
  50. WINDOW_FILE_DROP_CANCELLED = 'tauri://file-drop-cancelled',
  51. MENU = 'tauri://menu'
  52. }
  53. /**
  54. * Unregister the event listener associated with the given name and id.
  55. *
  56. * @ignore
  57. * @param event The event name
  58. * @param eventId Event identifier
  59. * @returns
  60. */
  61. async function _unlisten(event: string, eventId: number): Promise<void> {
  62. await invoke('plugin:event|unlisten', {
  63. event,
  64. eventId
  65. })
  66. }
  67. /**
  68. * Listen to an event. The event can be either global or window-specific.
  69. * See {@link Event.windowLabel} to check the event source.
  70. *
  71. * @example
  72. * ```typescript
  73. * import { listen } from '@tauri-apps/api/event';
  74. * const unlisten = await listen<string>('error', (event) => {
  75. * console.log(`Got error in window ${event.windowLabel}, payload: ${event.payload}`);
  76. * });
  77. *
  78. * // you need to call unlisten if your handler goes out of scope e.g. the component is unmounted
  79. * unlisten();
  80. * ```
  81. *
  82. * @param event Event name. Must include only alphanumeric characters, `-`, `/`, `:` and `_`.
  83. * @param handler Event handler callback.
  84. * @returns A promise resolving to a function to unlisten to the event.
  85. * Note that removing the listener is required if your listener goes out of scope e.g. the component is unmounted.
  86. *
  87. * @since 1.0.0
  88. */
  89. async function listen<T>(
  90. event: EventName,
  91. handler: EventCallback<T>,
  92. options?: Options
  93. ): Promise<UnlistenFn> {
  94. return invoke<number>('plugin:event|listen', {
  95. event,
  96. windowLabel: options?.target,
  97. handler: transformCallback(handler)
  98. }).then((eventId) => {
  99. return async () => _unlisten(event, eventId)
  100. })
  101. }
  102. /**
  103. * Listen to an one-off event. See {@link listen} for more information.
  104. *
  105. * @example
  106. * ```typescript
  107. * import { once } from '@tauri-apps/api/event';
  108. * interface LoadedPayload {
  109. * loggedIn: boolean,
  110. * token: string
  111. * }
  112. * const unlisten = await once<LoadedPayload>('loaded', (event) => {
  113. * console.log(`App is loaded, loggedIn: ${event.payload.loggedIn}, token: ${event.payload.token}`);
  114. * });
  115. *
  116. * // you need to call unlisten if your handler goes out of scope e.g. the component is unmounted
  117. * unlisten();
  118. * ```
  119. *
  120. * @param event Event name. Must include only alphanumeric characters, `-`, `/`, `:` and `_`.
  121. * @returns A promise resolving to a function to unlisten to the event.
  122. * Note that removing the listener is required if your listener goes out of scope e.g. the component is unmounted.
  123. *
  124. * @since 1.0.0
  125. */
  126. async function once<T>(
  127. event: EventName,
  128. handler: EventCallback<T>,
  129. options?: Options
  130. ): Promise<UnlistenFn> {
  131. return listen<T>(
  132. event,
  133. (eventData) => {
  134. handler(eventData)
  135. _unlisten(event, eventData.id).catch(() => {})
  136. },
  137. options
  138. )
  139. }
  140. /**
  141. * Emits an event to the backend and all Tauri windows.
  142. * @example
  143. * ```typescript
  144. * import { emit } from '@tauri-apps/api/event';
  145. * await emit('frontend-loaded', { loggedIn: true, token: 'authToken' });
  146. * ```
  147. *
  148. * @param event Event name. Must include only alphanumeric characters, `-`, `/`, `:` and `_`.
  149. *
  150. * @since 1.0.0
  151. */
  152. async function emit(
  153. event: string,
  154. payload?: unknown,
  155. options?: Options
  156. ): Promise<void> {
  157. await invoke('plugin:event|emit', {
  158. event,
  159. windowLabel: options?.target,
  160. payload
  161. })
  162. }
  163. export type { Event, EventCallback, UnlistenFn, EventName, Options }
  164. export { listen, once, emit, TauriEvent }