dialog.ts 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. // Copyright 2019-2021 Tauri Programme within The Commons Conservancy
  2. // SPDX-License-Identifier: Apache-2.0
  3. // SPDX-License-Identifier: MIT
  4. /**
  5. * Native system dialogs for opening and saving files.
  6. *
  7. * This package is also accessible with `window.__TAURI__.dialog` when `tauri.conf.json > build > withGlobalTauri` is set to true.
  8. *
  9. * The APIs must be allowlisted on `tauri.conf.json`:
  10. * ```json
  11. * {
  12. * "tauri": {
  13. * "allowlist": {
  14. * "dialog": {
  15. * "all": true, // enable all dialog APIs
  16. * "open": true, // enable file open API
  17. * "save": true // enable file save API
  18. * }
  19. * }
  20. * }
  21. * }
  22. * ```
  23. * It is recommended to allowlist only the APIs you use for optimal bundle size and security.
  24. * @module
  25. */
  26. import { invokeTauriCommand } from './helpers/tauri'
  27. /** Extension filters for the file dialog. */
  28. interface DialogFilter {
  29. /** Filter name. */
  30. name: string
  31. /**
  32. * Extensions to filter, without a `.` prefix.
  33. * @example
  34. * ```typescript
  35. * extensions: ['svg', 'png']
  36. * ```
  37. */
  38. extensions: string[]
  39. }
  40. /** Options for the open dialog. */
  41. interface OpenDialogOptions {
  42. /** The title of the dialog window. */
  43. title?: string
  44. /** The filters of the dialog. */
  45. filters?: DialogFilter[]
  46. /** Initial directory or file path. */
  47. defaultPath?: string
  48. /** Whether the dialog allows multiple selection or not. */
  49. multiple?: boolean
  50. /** Whether the dialog is a directory selection or not. */
  51. directory?: boolean
  52. /**
  53. * If `directory` is true, indicates that it will be read recursively later.
  54. * Defines whether subdirectories will be allowed on the scope or not.
  55. */
  56. recursive?: boolean
  57. }
  58. /** Options for the save dialog. */
  59. interface SaveDialogOptions {
  60. /** The title of the dialog window. */
  61. title?: string
  62. /** The filters of the dialog. */
  63. filters?: DialogFilter[]
  64. /**
  65. * Initial directory or file path.
  66. * If it's a directory path, the dialog interface will change to that folder.
  67. * If it's not an existing directory, the file name will be set to the dialog's file name input and the dialog will be set to the parent folder.
  68. */
  69. defaultPath?: string
  70. }
  71. /**
  72. * Open a file/directory selection dialog.
  73. *
  74. * The selected paths are added to the filesystem and asset protocol allowlist scopes.
  75. * When security is more important than the easy of use of this API,
  76. * prefer writing a dedicated command instead.
  77. *
  78. * Note that the allowlist scope change is not persisted, so the values are cleared when the application is restarted.
  79. * You can save it to the filesystem using [tauri-plugin-persisted-scope](https://github.com/tauri-apps/tauri-plugin-persisted-scope).
  80. *
  81. * @returns A promise resolving to the selected path(s)
  82. */
  83. async function open(
  84. options: OpenDialogOptions = {}
  85. ): Promise<null | string | string[]> {
  86. if (typeof options === 'object') {
  87. Object.freeze(options)
  88. }
  89. return invokeTauriCommand({
  90. __tauriModule: 'Dialog',
  91. message: {
  92. cmd: 'openDialog',
  93. options
  94. }
  95. })
  96. }
  97. /**
  98. * Open a file/directory save dialog.
  99. *
  100. * The selected path is added to the filesystem and asset protocol allowlist scopes.
  101. * When security is more important than the easy of use of this API,
  102. * prefer writing a dedicated command instead.
  103. *
  104. * Note that the allowlist scope change is not persisted, so the values are cleared when the application is restarted.
  105. * You can save it to the filesystem using [tauri-plugin-persisted-scope](https://github.com/tauri-apps/tauri-plugin-persisted-scope).
  106. *
  107. * @returns A promise resolving to the selected path.
  108. */
  109. async function save(options: SaveDialogOptions = {}): Promise<string> {
  110. if (typeof options === 'object') {
  111. Object.freeze(options)
  112. }
  113. return invokeTauriCommand({
  114. __tauriModule: 'Dialog',
  115. message: {
  116. cmd: 'saveDialog',
  117. options
  118. }
  119. })
  120. }
  121. /**
  122. * Shows a message dialog with an `Ok` button.
  123. *
  124. * @param {string} message The message to show.
  125. *
  126. * @return {Promise<void>} A promise indicating the success or failure of the operation.
  127. */
  128. async function message(message: string): Promise<void> {
  129. return invokeTauriCommand({
  130. __tauriModule: 'Dialog',
  131. message: {
  132. cmd: 'messageDialog',
  133. message
  134. }
  135. })
  136. }
  137. /**
  138. * Shows a question dialog with `Yes` and `No` buttons.
  139. *
  140. * @param {string} message The message to show.
  141. * @param {string|undefined} title The dialog's title. Defaults to the application name.
  142. *
  143. * @return {Promise<void>} A promise resolving to a boolean indicating whether `Yes` was clicked or not.
  144. */
  145. async function ask(message: string, title?: string): Promise<boolean> {
  146. return invokeTauriCommand({
  147. __tauriModule: 'Dialog',
  148. message: {
  149. cmd: 'askDialog',
  150. title,
  151. message
  152. }
  153. })
  154. }
  155. /**
  156. * Shows a question dialog with `Ok` and `Cancel` buttons.
  157. *
  158. * @param {string} message The message to show.
  159. * @param {string|undefined} title The dialog's title. Defaults to the application name.
  160. *
  161. * @return {Promise<void>} A promise resolving to a boolean indicating whether `Ok` was clicked or not.
  162. */
  163. async function confirm(message: string, title?: string): Promise<boolean> {
  164. return invokeTauriCommand({
  165. __tauriModule: 'Dialog',
  166. message: {
  167. cmd: 'confirmDialog',
  168. title,
  169. message
  170. }
  171. })
  172. }
  173. export type { DialogFilter, OpenDialogOptions, SaveDialogOptions }
  174. export { open, save, message, ask, confirm }