2022-08-28 21:13:21 +03:00
// Copyright 2019-2022 Tauri Programme within The Commons Conservancy
2021-04-11 01:09:09 +03:00
// 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
*
2022-07-11 16:14:31 +03:00
* This package is also accessible with ` window.__TAURI__.dialog ` when [ ` build.withGlobalTauri ` ] ( https : //tauri.app/v1/api/config/#buildconfig.withglobaltauri) in `tauri.conf.json` is set to `true`.
2021-05-18 04:33:09 +03:00
*
2022-07-11 16:14:31 +03:00
* The APIs must be added to [ ` tauri.allowlist.dialog ` ] ( https : //tauri.app/v1/api/config/#allowlistconfig.dialog) in `tauri.conf.json`:
2021-05-18 04:33:09 +03:00
* ` ` ` 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
2022-09-12 22:45:57 +03:00
/ * *
* Extension filters for the file dialog .
*
* @since 1.0 . 0
* /
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 [ ]
}
2022-09-12 22:45:57 +03:00
/ * *
* Options for the open dialog .
*
* @since 1.0 . 0
* /
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
}
2022-09-12 22:45:57 +03:00
/ * *
* Options for the save dialog .
*
* @since 1.0 . 0
* /
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-09-12 22:45:57 +03:00
/ * *
* @since 1.0 . 0
* /
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).
2022-06-30 23:52:43 +03:00
* @example
2022-06-13 03:44:33 +03:00
* ` ` ` typescript
* import { open } from '@tauri-apps/api/dialog' ;
2022-06-30 23:52:43 +03:00
* // Open a selection dialog for image files
2022-06-13 03:44:33 +03:00
* const selected = await open ( {
* multiple : true ,
2022-06-21 20:37:53 +03:00
* filters : [ {
2022-06-13 03:44:33 +03:00
* name : 'Image' ,
* extensions : [ 'png' , 'jpeg' ]
2022-06-21 20:37:53 +03:00
* } ]
2022-06-13 03:44:33 +03:00
* } ) ;
* if ( Array . isArray ( selected ) ) {
* // user selected multiple files
* } else if ( selected === null ) {
* // user cancelled the selection
* } else {
* // user selected a single file
* }
2022-06-14 16:09:53 +03:00
* ` ` `
2022-06-13 03:44:33 +03:00
*
2022-06-30 23:52:43 +03:00
* @example
2022-06-13 03:44:33 +03:00
* ` ` ` typescript
* import { open } from '@tauri-apps/api/dialog' ;
* import { appDir } from '@tauri-apps/api/path' ;
2022-06-30 23:52:43 +03:00
* // Open a selection dialog for directories
2022-06-13 03:44:33 +03:00
* const selected = await open ( {
* directory : true ,
* multiple : true ,
* defaultPath : await appDir ( ) ,
* } ) ;
* if ( Array . isArray ( selected ) ) {
* // user selected multiple directories
* } else if ( selected === null ) {
* // user cancelled the selection
* } else {
* // user selected a single directory
* }
* ` ` `
2021-04-13 04:44:50 +03:00
*
* @returns A promise resolving to the selected path ( s )
2022-09-12 22:45:57 +03:00
*
* @since 1.0 . 0
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).
2022-06-30 23:52:43 +03:00
* @example
2022-06-13 03:44:33 +03:00
* ` ` ` typescript
* import { save } from '@tauri-apps/api/dialog' ;
* const filePath = await save ( {
* multiple : true ,
2022-06-21 20:37:53 +03:00
* filters : [ {
2022-06-13 03:44:33 +03:00
* name : 'Image' ,
* extensions : [ 'stronghold' ]
2022-06-21 20:37:53 +03:00
* } ]
2022-06-13 03:44:33 +03:00
* } ) ;
* ` ` `
2022-03-03 21:41:58 +03:00
*
2021-04-13 04:44:50 +03:00
* @returns A promise resolving to the selected path .
2022-09-12 22:45:57 +03:00
*
* @since 1.0 . 0
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 .
2022-06-13 03:44:33 +03:00
* @example
* ` ` ` typescript
* import { message } from '@tauri-apps/api/dialog' ;
* await message ( 'Tauri is awesome' , 'Tauri' ) ;
* await message ( 'File not found' , { title : 'Tauri' , type : 'error' } ) ;
* ` ` `
2021-10-02 22:13:24 +03:00
*
2022-09-12 22:45:57 +03:00
* @param message The message to show .
* @param options The dialog ' s options . If a string , it represents the dialog title .
*
* @returns A promise indicating the success or failure of the operation .
*
* @since 1.0 . 0
2021-10-02 22:13:24 +03:00
*
* /
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-07-05 04:30:06 +03:00
message : message.toString ( ) ,
title : opts?.title?.toString ( ) ,
2022-05-21 17:24:39 +03:00
type : opts ? . type
2021-10-02 22:13:24 +03:00
}
} )
}
/ * *
* Shows a question dialog with ` Yes ` and ` No ` buttons .
2022-06-13 03:44:33 +03:00
* @example
* ` ` ` typescript
* import { ask } from '@tauri-apps/api/dialog' ;
* const yes = await ask ( 'Are you sure?' , 'Tauri' ) ;
* const yes2 = await ask ( 'This action cannot be reverted. Are you sure?' , { title : 'Tauri' , type : 'warning' } ) ;
* ` ` `
2021-10-02 22:13:24 +03:00
*
2022-09-12 22:45:57 +03:00
* @param message The message to show .
* @param options The dialog ' s options . If a string , it represents the dialog title .
2021-10-02 22:13:24 +03:00
*
2022-09-12 22:45:57 +03:00
* @returns A promise resolving to a boolean indicating whether ` Yes ` was clicked or not .
*
* @since 1.0 . 0
2021-10-02 22:13:24 +03:00
* /
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-07-05 04:30:06 +03:00
message : message.toString ( ) ,
title : opts?.title?.toString ( ) ,
2022-05-21 17:24:39 +03:00
type : opts ? . type
2021-10-02 22:13:24 +03:00
}
} )
}
/ * *
* Shows a question dialog with ` Ok ` and ` Cancel ` buttons .
2022-06-13 03:44:33 +03:00
* @example
* ` ` ` typescript
* import { confirm } from '@tauri-apps/api/dialog' ;
2022-06-20 04:38:44 +03:00
* const confirmed = await confirm ( 'Are you sure?' , 'Tauri' ) ;
* const confirmed2 = await confirm ( 'This action cannot be reverted. Are you sure?' , { title : 'Tauri' , type : 'warning' } ) ;
2022-06-13 03:44:33 +03:00
* ` ` `
2021-10-02 22:13:24 +03:00
*
2022-09-12 22:45:57 +03:00
* @param message The message to show .
* @param options The dialog ' s options . If a string , it represents the dialog title .
*
* @returns A promise resolving to a boolean indicating whether ` Ok ` was clicked or not .
2021-10-02 22:13:24 +03:00
*
2022-09-12 22:45:57 +03:00
* @since 1.0 . 0
2021-10-02 22:13:24 +03:00
* /
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-07-05 04:30:06 +03:00
message : message.toString ( ) ,
title : opts?.title?.toString ( ) ,
2022-05-21 17:24:39 +03:00
type : opts ? . type
2021-10-02 22:13:24 +03:00
}
} )
}
2022-05-29 16:10:41 +03:00
export type {
DialogFilter ,
OpenDialogOptions ,
SaveDialogOptions ,
MessageDialogOptions
}
2021-05-17 18:54:56 +03:00
2021-10-02 22:13:24 +03:00
export { open , save , message , ask , confirm }