2021-04-11 01:09:09 +03:00
|
|
|
// Copyright 2019-2021 Tauri Programme within The Commons Conservancy
|
|
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
|
2021-05-05 20:36:40 +03:00
|
|
|
/**
|
|
|
|
* Native system dialogs for opening and saving files.
|
2021-05-18 04:33:09 +03:00
|
|
|
*
|
2021-05-17 23:56:14 +03:00
|
|
|
* This package is also accessible with `window.__TAURI__.dialog` when `tauri.conf.json > build > withGlobalTauri` is set to true.
|
2021-05-18 04:33:09 +03:00
|
|
|
*
|
|
|
|
* The APIs must be allowlisted on `tauri.conf.json`:
|
|
|
|
* ```json
|
|
|
|
* {
|
|
|
|
* "tauri": {
|
|
|
|
* "allowlist": {
|
|
|
|
* "dialog": {
|
|
|
|
* "all": true, // enable all dialog APIs
|
|
|
|
* "open": true, // enable file open API
|
|
|
|
* "save": true // enable file save API
|
|
|
|
* }
|
|
|
|
* }
|
|
|
|
* }
|
|
|
|
* }
|
|
|
|
* ```
|
|
|
|
* It is recommended to allowlist only the APIs you use for optimal bundle size and security.
|
2021-07-21 07:23:16 +03:00
|
|
|
* @module
|
2021-05-05 20:36:40 +03:00
|
|
|
*/
|
|
|
|
|
2021-03-07 05:19:12 +03:00
|
|
|
import { invokeTauriCommand } from './helpers/tauri'
|
2020-06-27 18:20:00 +03:00
|
|
|
|
2021-05-05 20:36:40 +03:00
|
|
|
/** Extension filters for the file dialog. */
|
2021-05-17 18:54:56 +03:00
|
|
|
interface DialogFilter {
|
2021-05-05 20:36:40 +03:00
|
|
|
/** Filter name. */
|
2021-02-18 17:43:41 +03:00
|
|
|
name: string
|
2021-05-05 20:36:40 +03:00
|
|
|
/**
|
|
|
|
* Extensions to filter, without a `.` prefix.
|
|
|
|
* @example
|
|
|
|
* ```typescript
|
|
|
|
* extensions: ['svg', 'png']
|
|
|
|
* ```
|
|
|
|
*/
|
2021-02-18 17:43:41 +03:00
|
|
|
extensions: string[]
|
|
|
|
}
|
|
|
|
|
2021-05-05 20:36:40 +03:00
|
|
|
/** Options for the open dialog. */
|
2021-05-17 18:54:56 +03:00
|
|
|
interface OpenDialogOptions {
|
2022-01-16 21:41:11 +03:00
|
|
|
/** The title of the dialog window. */
|
|
|
|
title?: string
|
2021-05-05 20:36:40 +03:00
|
|
|
/** The filters of the dialog. */
|
2021-02-18 17:43:41 +03:00
|
|
|
filters?: DialogFilter[]
|
2021-12-27 19:03:51 +03:00
|
|
|
/** Initial directory or file path. */
|
2021-02-09 21:22:04 +03:00
|
|
|
defaultPath?: string
|
2021-05-05 20:36:40 +03:00
|
|
|
/** Whether the dialog allows multiple selection or not. */
|
2021-02-09 21:22:04 +03:00
|
|
|
multiple?: boolean
|
2021-05-05 20:36:40 +03:00
|
|
|
/** Whether the dialog is a directory selection or not. */
|
2021-02-09 21:22:04 +03:00
|
|
|
directory?: boolean
|
2022-03-03 21:41:58 +03:00
|
|
|
/**
|
|
|
|
* If `directory` is true, indicates that it will be read recursively later.
|
|
|
|
* Defines whether subdirectories will be allowed on the scope or not.
|
|
|
|
*/
|
|
|
|
recursive?: boolean
|
2020-07-13 01:34:44 +03:00
|
|
|
}
|
|
|
|
|
2021-05-05 20:36:40 +03:00
|
|
|
/** Options for the save dialog. */
|
2021-05-17 18:54:56 +03:00
|
|
|
interface SaveDialogOptions {
|
2022-01-16 21:41:11 +03:00
|
|
|
/** The title of the dialog window. */
|
|
|
|
title?: string
|
2021-05-05 20:36:40 +03:00
|
|
|
/** The filters of the dialog. */
|
2021-02-18 17:43:41 +03:00
|
|
|
filters?: DialogFilter[]
|
2021-08-10 21:28:24 +03:00
|
|
|
/**
|
|
|
|
* Initial directory or file path.
|
|
|
|
* If it's a directory path, the dialog interface will change to that folder.
|
|
|
|
* 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.
|
|
|
|
*/
|
2021-02-18 17:43:41 +03:00
|
|
|
defaultPath?: string
|
|
|
|
}
|
2020-07-13 01:34:44 +03:00
|
|
|
|
2022-05-21 17:24:39 +03:00
|
|
|
interface MessageDialogOptions {
|
|
|
|
/** The title of the dialog. Defaults to the app name. */
|
|
|
|
title?: string
|
|
|
|
/** The type of the dialog. Defaults to `info`. */
|
|
|
|
type?: 'info' | 'warning' | 'error'
|
|
|
|
}
|
|
|
|
|
2020-06-27 18:20:00 +03:00
|
|
|
/**
|
2022-03-03 21:41:58 +03:00
|
|
|
* Open a file/directory selection dialog.
|
|
|
|
*
|
|
|
|
* The selected paths are added to the filesystem and asset protocol allowlist scopes.
|
|
|
|
* When security is more important than the easy of use of this API,
|
|
|
|
* prefer writing a dedicated command instead.
|
|
|
|
*
|
|
|
|
* Note that the allowlist scope change is not persisted, so the values are cleared when the application is restarted.
|
|
|
|
* You can save it to the filesystem using [tauri-plugin-persisted-scope](https://github.com/tauri-apps/tauri-plugin-persisted-scope).
|
2021-04-13 04:44:50 +03:00
|
|
|
*
|
|
|
|
* @returns A promise resolving to the selected path(s)
|
2020-06-27 18:20:00 +03:00
|
|
|
*/
|
2020-08-08 03:54:17 +03:00
|
|
|
async function open(
|
|
|
|
options: OpenDialogOptions = {}
|
2022-04-17 20:30:36 +03:00
|
|
|
): Promise<null | string | string[]> {
|
2021-02-09 21:22:04 +03:00
|
|
|
if (typeof options === 'object') {
|
|
|
|
Object.freeze(options)
|
2020-06-27 18:20:00 +03:00
|
|
|
}
|
|
|
|
|
2021-10-02 22:13:24 +03:00
|
|
|
return invokeTauriCommand({
|
2021-02-16 07:23:15 +03:00
|
|
|
__tauriModule: 'Dialog',
|
2021-02-12 08:42:40 +03:00
|
|
|
message: {
|
|
|
|
cmd: 'openDialog',
|
|
|
|
options
|
|
|
|
}
|
2021-02-09 21:22:04 +03:00
|
|
|
})
|
2020-06-27 18:20:00 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2021-04-13 04:44:50 +03:00
|
|
|
* Open a file/directory save dialog.
|
|
|
|
*
|
2022-03-03 21:41:58 +03:00
|
|
|
* The selected path is added to the filesystem and asset protocol allowlist scopes.
|
|
|
|
* When security is more important than the easy of use of this API,
|
|
|
|
* prefer writing a dedicated command instead.
|
|
|
|
*
|
|
|
|
* Note that the allowlist scope change is not persisted, so the values are cleared when the application is restarted.
|
|
|
|
* You can save it to the filesystem using [tauri-plugin-persisted-scope](https://github.com/tauri-apps/tauri-plugin-persisted-scope).
|
|
|
|
*
|
2021-04-13 04:44:50 +03:00
|
|
|
* @returns A promise resolving to the selected path.
|
2020-06-27 18:20:00 +03:00
|
|
|
*/
|
2020-08-08 03:54:17 +03:00
|
|
|
async function save(options: SaveDialogOptions = {}): Promise<string> {
|
2021-02-09 21:22:04 +03:00
|
|
|
if (typeof options === 'object') {
|
|
|
|
Object.freeze(options)
|
2020-06-27 18:20:00 +03:00
|
|
|
}
|
|
|
|
|
2021-10-02 22:13:24 +03:00
|
|
|
return invokeTauriCommand({
|
2021-02-16 07:23:15 +03:00
|
|
|
__tauriModule: 'Dialog',
|
2021-02-12 08:42:40 +03:00
|
|
|
message: {
|
|
|
|
cmd: 'saveDialog',
|
|
|
|
options
|
|
|
|
}
|
2021-02-09 21:22:04 +03:00
|
|
|
})
|
2020-06-27 18:20:00 +03:00
|
|
|
}
|
|
|
|
|
2021-10-02 22:13:24 +03:00
|
|
|
/**
|
|
|
|
* Shows a message dialog with an `Ok` button.
|
|
|
|
*
|
|
|
|
* @param {string} message The message to show.
|
2022-05-21 17:24:39 +03:00
|
|
|
* @param {string|MessageDialogOptions|undefined} options The dialog's options. If a string, it represents the dialog title.
|
2021-10-02 22:13:24 +03:00
|
|
|
*
|
|
|
|
* @return {Promise<void>} A promise indicating the success or failure of the operation.
|
|
|
|
*/
|
2022-05-21 17:24:39 +03:00
|
|
|
async function message(
|
|
|
|
message: string,
|
|
|
|
options?: string | MessageDialogOptions
|
|
|
|
): Promise<void> {
|
|
|
|
const opts = typeof options === 'string' ? { title: options } : options
|
2021-10-02 22:13:24 +03:00
|
|
|
return invokeTauriCommand({
|
|
|
|
__tauriModule: 'Dialog',
|
|
|
|
message: {
|
|
|
|
cmd: 'messageDialog',
|
2022-05-21 17:24:39 +03:00
|
|
|
message,
|
|
|
|
title: opts?.title,
|
|
|
|
type: opts?.type
|
2021-10-02 22:13:24 +03:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Shows a question dialog with `Yes` and `No` buttons.
|
|
|
|
*
|
|
|
|
* @param {string} message The message to show.
|
2022-05-21 17:24:39 +03:00
|
|
|
* @param {string|MessageDialogOptions|undefined} options The dialog's options. If a string, it represents the dialog title.
|
2021-10-02 22:13:24 +03:00
|
|
|
*
|
|
|
|
* @return {Promise<void>} A promise resolving to a boolean indicating whether `Yes` was clicked or not.
|
|
|
|
*/
|
2022-05-21 17:24:39 +03:00
|
|
|
async function ask(
|
|
|
|
message: string,
|
|
|
|
options?: string | MessageDialogOptions
|
|
|
|
): Promise<boolean> {
|
|
|
|
const opts = typeof options === 'string' ? { title: options } : options
|
2021-10-02 22:13:24 +03:00
|
|
|
return invokeTauriCommand({
|
|
|
|
__tauriModule: 'Dialog',
|
|
|
|
message: {
|
|
|
|
cmd: 'askDialog',
|
2022-05-21 17:24:39 +03:00
|
|
|
message,
|
|
|
|
title: opts?.title,
|
|
|
|
type: opts?.type
|
2021-10-02 22:13:24 +03:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Shows a question dialog with `Ok` and `Cancel` buttons.
|
|
|
|
*
|
|
|
|
* @param {string} message The message to show.
|
2022-05-21 17:24:39 +03:00
|
|
|
* @param {string|MessageDialogOptions|undefined} options The dialog's options. If a string, it represents the dialog title.
|
2021-10-02 22:13:24 +03:00
|
|
|
*
|
|
|
|
* @return {Promise<void>} A promise resolving to a boolean indicating whether `Ok` was clicked or not.
|
|
|
|
*/
|
2022-05-21 17:24:39 +03:00
|
|
|
async function confirm(
|
|
|
|
message: string,
|
|
|
|
options?: string | MessageDialogOptions
|
|
|
|
): Promise<boolean> {
|
|
|
|
const opts = typeof options === 'string' ? { title: options } : options
|
2021-10-02 22:13:24 +03:00
|
|
|
return invokeTauriCommand({
|
|
|
|
__tauriModule: 'Dialog',
|
|
|
|
message: {
|
|
|
|
cmd: 'confirmDialog',
|
2022-05-21 17:24:39 +03:00
|
|
|
message,
|
|
|
|
title: opts?.title,
|
|
|
|
type: opts?.type
|
2021-10-02 22:13:24 +03:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2021-05-17 18:54:56 +03:00
|
|
|
export type { DialogFilter, OpenDialogOptions, SaveDialogOptions }
|
|
|
|
|
2021-10-02 22:13:24 +03:00
|
|
|
export { open, save, message, ask, confirm }
|