rework dialog module

This commit is contained in:
Jonas Kruckenberg 2022-11-14 14:01:25 +01:00
parent 44b0a5491b
commit 1046f51149

View file

@ -1,267 +1,589 @@
//! User interaction with the file system using dialog boxes.
//!
//! # Example
//!
//! ```rust,no_run
//! use tauri_api::dialog::open;
//!
//! let path = open(None).await;
//! ```
use serde::Serialize; use serde::Serialize;
use std::path::PathBuf; use std::path::{Path, PathBuf};
/// Extension filter for the file dialog. #[derive(Debug, Serialize)]
/// struct DialogFilter<'a> {
/// # Example extensions: &'a [&'a str],
/// name: &'a str,
/// ```rust,no_run
/// let filter = DialogFilter {
/// extension: vec![".jpg", ".jpeg", ".png", ".bmp"],
/// name: "images",
/// };
/// ```
#[derive(Serialize)]
pub struct DialogFilter {
/// Extensions to filter, without a `.` prefix.
pub extensions: Vec<String>,
/// Filter name
pub name: String,
} }
/// Types of a [`message`] dialog. #[derive(Debug, Default, Serialize)]
#[derive(Serialize)] #[serde(rename = "camelCase")]
pub struct FileDialogBuilder<'a> {
default_path: Option<&'a Path>,
filters: Vec<DialogFilter<'a>>,
title: Option<&'a str>,
directory: bool,
multiple: bool,
recursive: bool,
}
impl<'a> FileDialogBuilder<'a> {
/// Gets the default file dialog builder.
pub fn new() -> Self {
Self::default()
}
/// Set starting file name or directory of the dialog.
pub fn set_default_path(&mut self, default_path: &'a Path) {
self.default_path = Some(default_path);
}
/// If directory is true, indicates that it will be read recursively later.
/// Defines whether subdirectories will be allowed on the scope or not.
///
/// # Example
///
/// ```rust
/// use tauri_sys::dialog::FileDialogBuilder;
///
/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let _builder = FileDialogBuilder::new().set_recursive(true);
/// # Ok(())
/// # }
/// ```
pub fn set_recursive(&mut self, recursive: bool) {
self.recursive = recursive;
}
/// Set the title of the dialog.
///
/// # Example
///
/// ```rust
/// use tauri_sys::dialog::FileDialogBuilder;
///
/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let _builder = FileDialogBuilder::new().set_title("Test Title");
/// # Ok(())
/// # }
/// ```
pub fn set_title(&mut self, title: &'a str) {
self.title = Some(title);
}
/// Add file extension filter. Takes in the name of the filter, and list of extensions
///
/// # Example
///
/// ```rust
/// use tauri_sys::dialog::FileDialogBuilder;
///
/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let _builder = FileDialogBuilder::new().add_filter("Image", &["png", "jpeg"]);
/// # Ok(())
/// # }
/// ```
pub fn add_filter(&mut self, name: &'a str, extensions: &'a [&'a str]) {
self.filters.push(DialogFilter { name, extensions });
}
/// Add many file extension filters.
///
/// # Example
///
/// ```rust
/// use tauri_sys::dialog::FileDialogBuilder;
///
/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let _builder = FileDialogBuilder::new().add_filters(&[("Image", &["png", "jpeg"]),("Video", &["mp4"])]);
/// # Ok(())
/// # }
/// ```
pub fn add_filters(&mut self, filters: impl IntoIterator<Item = (&'a str, &'a [&'a str])>) {
for (name, extensions) in filters.into_iter() {
self.filters.push(DialogFilter {
name: name.as_ref(),
extensions,
});
}
}
/// Shows the dialog to select a single file.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_sys::dialog::FileDialogBuilder;
///
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let file = FileDialogBuilder::new().pick_file().await?;
/// # Ok(())
/// # }
/// ```
pub async fn pick_file(self) -> crate::Result<Option<PathBuf>> {
let raw = inner::open(serde_wasm_bindgen::to_value(&self)?).await?;
Ok(serde_wasm_bindgen::from_value(raw)?)
}
/// Shows the dialog to select multiple files.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_sys::dialog::FileDialogBuilder;
///
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let files = FileDialogBuilder::new().pick_files().await?;
/// # Ok(())
/// # }
/// ```
pub async fn pick_files(mut self) -> crate::Result<Option<Vec<PathBuf>>> {
self.multiple = true;
let raw = inner::open(serde_wasm_bindgen::to_value(&self)?).await?;
Ok(serde_wasm_bindgen::from_value(raw)?)
}
/// Shows the dialog to select a single folder.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_sys::dialog::FileDialogBuilder;
///
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let files = FileDialogBuilder::new().pick_folder().await?;
/// # Ok(())
/// # }
/// ```
pub async fn pick_folder(mut self) -> crate::Result<Option<PathBuf>> {
self.directory = true;
let raw = inner::open(serde_wasm_bindgen::to_value(&self)?).await?;
Ok(serde_wasm_bindgen::from_value(raw)?)
}
/// Shows the dialog to select multiple folders.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_sys::dialog::FileDialogBuilder;
///
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let files = FileDialogBuilder::new().pick_folders().await?;
/// # Ok(())
/// # }
/// ```
pub async fn pick_folders(mut self) -> crate::Result<Option<Vec<PathBuf>>> {
self.directory = true;
self.multiple = true;
let raw = inner::open(serde_wasm_bindgen::to_value(&self)?).await?;
Ok(serde_wasm_bindgen::from_value(raw)?)
}
/// Open a file/directory save dialog.
///
/// 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.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_sys::dialog::FileDialogBuilder;
///
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let file = FileDialogBuilder::new().save().await?;
/// # Ok(())
/// # }
/// ```
pub async fn save(self) -> crate::Result<Option<PathBuf>> {
let raw = inner::save(serde_wasm_bindgen::to_value(&self)?).await?;
Ok(serde_wasm_bindgen::from_value(raw)?)
}
}
#[derive(Debug, Default)]
pub enum MessageDialogType { pub enum MessageDialogType {
Error, #[default]
Info, Info,
Warning, Warning,
Error,
} }
/// Options for the [`message`] dialog. impl Serialize for MessageDialogType {
#[derive(Serialize)] fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
pub struct MessageDialogOptions { where
/// The title of the dialog. Defaults to the app name. S: serde::Serializer,
pub title: Option<String>, {
match self {
/// The type of the dialog. Defaults to MessageDialogType::Info. MessageDialogType::Info => serializer.serialize_str("info"),
#[serde(rename(serialize = "type"))] MessageDialogType::Warning => serializer.serialize_str("warning"),
pub kind: MessageDialogType, MessageDialogType::Error => serializer.serialize_str("error"),
}
}
} }
impl MessageDialogOptions { #[derive(Debug, Default, Serialize)]
/// Creates a new `MessageDialogOptions` with sensible default values. pub struct MessageDialogBuilder<'a> {
title: Option<&'a str>,
r#type: MessageDialogType,
}
impl<'a> MessageDialogBuilder<'a> {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self::default()
title: None,
kind: MessageDialogType::Info,
} }
/// Set the title of the dialog.
///
/// # Example
///
/// ```rust
/// use tauri_sys::dialog::MessageDialogBuilder;
///
/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let _builder = MessageDialogBuilder::new().set_title("Test Title");
/// # Ok(())
/// # }
/// ```
pub fn set_title(&mut self, title: &'a str) {
self.title = Some(title);
}
/// Set the type of the dialog.
///
/// # Example
///
/// ```rust
/// use tauri_sys::dialog::{MessageDialogBuilder,MessageDialogType};
///
/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let _builder = MessageDialogBuilder::new().set_type(MessageDialogType::Error);
/// # Ok(())
/// # }
/// ```
pub fn set_type(&mut self, r#type: MessageDialogType) {
self.r#type = r#type;
}
/// Shows a message dialog with an `Ok` button.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_sys::dialog::MessageDialogBuilder;
///
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let file = MessageDialogBuilder::new().message("Tauri is awesome").await?;
/// # Ok(())
/// # }
/// ```
pub async fn message(self, message: &str) -> crate::Result<()> {
Ok(inner::message(message, serde_wasm_bindgen::to_value(&self)?).await?)
}
/// Shows a question dialog with `Yes` and `No` buttons.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_sys::dialog::MessageDialogBuilder;
///
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let confirmation = MessageDialogBuilder::new().ask("Are you sure?").await?;
/// # Ok(())
/// # }
/// ```
pub async fn ask(self, message: &str) -> crate::Result<bool> {
let raw = inner::ask(message, serde_wasm_bindgen::to_value(&self)?).await?;
Ok(serde_wasm_bindgen::from_value(raw)?)
}
/// Shows a question dialog with `Ok` and `Cancel` buttons.
///
/// # Example
///
/// ```rust,no_run
/// use tauri_sys::dialog::MessageDialogBuilder;
///
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let confirmation = MessageDialogBuilder::new().confirm("Are you sure?").await?;
/// # Ok(())
/// # }
/// ```
pub async fn confirm(self, message: &str) -> crate::Result<bool> {
let raw = inner::confirm(message, serde_wasm_bindgen::to_value(&self)?).await?;
Ok(serde_wasm_bindgen::from_value(raw)?)
} }
} }
/// Options for an [`open`] dialog. // //! User interaction with the file system using dialog boxes.
#[derive(Serialize)] // //!
pub struct OpenDialogOptions { // //! # Example
/// Initial directory or file path. // //!
#[serde(rename(serialize = "defaultPath"))] // //! ```rust,no_run
pub default_path: Option<PathBuf>, // //! use tauri_api::dialog::open;
// //!
// //! let path = open(None).await;
// //! ```
// use serde::Serialize;
// use std::path::PathBuf;
/// Whether the dialog is a directory selection or not. // /// Extension filter for the file dialog.
pub directory: bool, // ///
// /// # Example
// ///
// /// ```rust,no_run
// /// let filter = DialogFilter {
// /// extension: vec![".jpg", ".jpeg", ".png", ".bmp"],
// /// name: "images",
// /// };
// /// ```
// #[derive(Serialize)]
// pub struct DialogFilter {
// /// Extensions to filter, without a `.` prefix.
// pub extensions: Vec<String>,
/// The filters of the dialog. // /// Filter name
pub filters: Vec<DialogFilter>, // pub name: String,
// }
/// Whether the dialgo allows multiple selection or not. // /// Types of a [`message`] dialog.
pub multiple: bool, // #[derive(Serialize)]
// pub enum MessageDialogType {
// Error,
// Info,
// Warning,
// }
/// If `directory` is `true`, indicatees that it will be read recursivley later. // /// Options for the [`message`] dialog.
/// Defines whether subdirectories will be allowed on the scope or not. // #[derive(Serialize)]
pub recursive: bool, // pub struct MessageDialogOptions {
// /// The title of the dialog. Defaults to the app name.
// pub title: Option<String>,
/// The title of the dialog window. // /// The type of the dialog. Defaults to MessageDialogType::Info.
pub title: Option<String>, // #[serde(rename(serialize = "type"))]
} // pub kind: MessageDialogType,
// }
impl OpenDialogOptions { // impl MessageDialogOptions {
/// Creates a new `OpenDialogOptions` with sensible default values. // /// Creates a new `MessageDialogOptions` with sensible default values.
pub fn new() -> Self { // pub fn new() -> Self {
Self { // Self {
default_path: None, // title: None,
directory: false, // kind: MessageDialogType::Info,
filters: Vec::new(), // }
multiple: false, // }
recursive: false, // }
title: None,
}
}
}
/// Options for the save dialog. // /// Options for an [`open`] dialog.
#[derive(Serialize)] // #[derive(Serialize)]
pub struct SaveDialogOptions { // pub struct OpenDialogOptions {
/// Initial directory of the file path. // /// Initial directory or file path.
/// If it's not a directory path, the dialog interface will change to that folder. // #[serde(rename(serialize = "defaultPath"))]
/// If it's not an existing directory, the file name will be set to the dialog's // pub default_path: Option<PathBuf>,
/// file name input and the dialog will be set to the parent folder.
#[serde(rename(serialize = "defaultPath"))]
pub default_path: Option<PathBuf>,
/// The filters of the dialog. // /// Whether the dialog is a directory selection or not.
pub filters: Vec<DialogFilter>, // pub directory: bool,
/// The title of the dialog window. // /// The filters of the dialog.
pub title: Option<String>, // pub filters: Vec<DialogFilter>,
}
impl SaveDialogOptions { // /// Whether the dialog allows multiple selection or not.
/// Creates a new `SaveDialogOptions` with sensible default values. // pub multiple: bool,
pub fn new() -> Self {
Self {
default_path: None,
filters: Vec::new(),
title: None,
}
}
}
/// Show a question dialog with `Yes` and `No` buttons. // /// If `directory` is `true`, indicatees that it will be read recursivley later.
/// // /// Defines whether subdirectories will be allowed on the scope or not.
/// # Example // pub recursive: bool,
///
/// ```rust,no_run
/// use tauri_api::dialog::{ask, MessageDialogOptions};
///
/// let yes = ask("Are you sure?", None).await;
/// ```
/// @param message Message to display.
/// @param options Dialog options.
/// @returns Whether the user selected `Yes` or `No`.
#[inline(always)]
pub async fn ask(message: &str, options: Option<MessageDialogOptions>) -> crate::Result<bool> {
let js_val = inner::ask(message, serde_wasm_bindgen::to_value(&options)?).await?;
Ok(serde_wasm_bindgen::from_value(js_val)?) // /// The title of the dialog window.
} // pub title: Option<String>,
// }
/// Shows a question dialog with `Ok` and `Cancel` buttons. // impl OpenDialogOptions {
/// // /// Creates a new `OpenDialogOptions` with sensible default values.
/// # Example // pub fn new() -> Self {
/// // Self {
/// ```rust,no_run // default_path: None,
/// use tauri_api::dialog::{confirm, MessageDialogOptions}; // directory: false,
/// // filters: Vec::new(),
/// let confirmed = confirm("Are you sure?", None).await; // multiple: false,
/// ``` // recursive: false,
/// @returns Whether the user selelced `Ok` or `Cancel`. // title: None,
pub async fn confirm(message: &str, options: Option<MessageDialogOptions>) -> crate::Result<bool> { // }
let js_val = inner::confirm(message, serde_wasm_bindgen::to_value(&options)?).await?; // }
// }
Ok(serde_wasm_bindgen::from_value(js_val)?) // /// Options for the save dialog.
} // #[derive(Serialize)]
// pub struct SaveDialogOptions {
// /// Initial directory of the file path.
// /// If it's not 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.
// #[serde(rename(serialize = "defaultPath"))]
// pub default_path: Option<PathBuf>,
/// Shows a message dialog with an `Ok` button. // /// The filters of the dialog.
/// // pub filters: Vec<DialogFilter>,
/// # Example
///
/// ```rust,no_run
/// use tauri_api::dialog::{message, MessageDialogOptions};
///
/// message("Tauri is awesome", None).await;
/// ```
/// @param message Message to display.
/// @param options Dialog options.
/// @returns Promise resolved when user closes the dialog.
pub async fn message(message: &str, options: Option<MessageDialogOptions>) -> crate::Result<()> {
Ok(inner::message(message, serde_wasm_bindgen::to_value(&options)?).await?)
}
/// Opens a file/directory selection dialog for a single file. // /// The title of the dialog window.
/// `multiple` field of [`options`](OpenDialogOptions) must be `false`, if provided. // pub title: Option<String>,
/// // }
/// The selected paths are added to the filesystem and asset protocol allowlist scopes.
/// When security is mroe important than the ease of use of this API,
/// prefer writing a dedicated command instead.
///
/// Note that the allowlist scope change is not persisited,
/// so the values are cleared when the applicaiton is restarted.
/// You can save it to the filessytem using the [tauri-plugin-persisted-scope](https://github.com/tauri-apps/tauri-plugin-persisted-scope).
///
/// # Example
///
/// ```rust,no_run
/// use tauri_api::dialog::{open, OpenDialogOptions};
///
/// let file = open(None).await;
///
/// let mut opts = OpenDialogOptions::new();
/// opts.directory = true;
/// let dir = open(Some(opts)).await;
/// ```
/// @param options Dialog options.
/// @returns List of file paths, or `None` if user cancelled the dialog.
pub async fn open(options: Option<OpenDialogOptions>) -> crate::Result<Option<PathBuf>> {
let file = inner::open(serde_wasm_bindgen::to_value(&options)?).await?;
Ok(serde_wasm_bindgen::from_value(file)?) // impl SaveDialogOptions {
} // /// Creates a new `SaveDialogOptions` with sensible default values.
// pub fn new() -> Self {
// Self {
// default_path: None,
// filters: Vec::new(),
// title: None,
// }
// }
// }
/// Opens a file/directory selection dialog for multiple files. // /// Show a question dialog with `Yes` and `No` buttons.
/// `multiple` field of [`options`](OpenDialogOptions) must be `true`, if provided. // ///
/// // /// # Example
/// The selected paths are added to the filesystem and asset protocol allowlist scopes. // ///
/// When security is mroe important than the ease of use of this API, // /// ```rust,no_run
/// prefer writing a dedicated command instead. // /// use tauri_api::dialog::{ask, MessageDialogOptions};
/// // ///
/// Note that the allowlist scope change is not persisited, // /// let yes = ask("Are you sure?", None).await;
/// so the values are cleared when the applicaiton is restarted. // /// ```
/// You can save it to the filessytem using the [tauri-plugin-persisted-scope](https://github.com/tauri-apps/tauri-plugin-persisted-scope). // /// @param message Message to display.
/// // /// @param options Dialog options.
/// # Example // /// @returns Whether the user selected `Yes` or `No`.
/// // #[inline(always)]
/// ```rust,no_run // pub async fn ask(message: &str, options: Option<MessageDialogOptions>) -> crate::Result<bool> {
/// use tauri_api::dialog::{open, OpenDialogOptions}; // let js_val = inner::ask(message, serde_wasm_bindgen::to_value(&options)?).await?;
///
/// let files = open_multiple(None).await;
///
/// let mut opts = OpenDialogOptions::new();
/// opts.multiple = true;
/// opts.directory = true;
/// let dirs = open(Some(opts)).await;
/// ```
/// @param options Dialog options.
/// @returns List of file paths, or `None` if user cancelled the dialog.
pub async fn open_multiple(
options: Option<OpenDialogOptions>,
) -> crate::Result<Option<Vec<PathBuf>>> {
let files = inner::open_multiple(serde_wasm_bindgen::to_value(&options)?).await?;
Ok(serde_wasm_bindgen::from_value(files)?) // Ok(serde_wasm_bindgen::from_value(js_val)?)
} // }
/// Opens a file/directory save dialog. // /// Shows a question dialog with `Ok` and `Cancel` buttons.
/// // ///
/// The selected paths are added to the filesystem and asset protocol allowlist scopes. // /// # Example
/// When security is mroe important than the ease of use of this API, // ///
/// prefer writing a dedicated command instead. // /// ```rust,no_run
/// // /// use tauri_api::dialog::{confirm, MessageDialogOptions};
/// Note that the allowlist scope change is not persisited, // ///
/// so the values are cleared when the applicaiton is restarted. // /// let confirmed = confirm("Are you sure?", None).await;
/// You can save it to the filessytem using the [tauri-plugin-persisted-scope](https://github.com/tauri-apps/tauri-plugin-persisted-scope). // /// ```
/// // /// @returns Whether the user selelced `Ok` or `Cancel`.
/// # Example // pub async fn confirm(message: &str, options: Option<MessageDialogOptions>) -> crate::Result<bool> {
/// // let js_val = inner::confirm(message, serde_wasm_bindgen::to_value(&options)?).await?;
/// ```rust,no_run
/// use tauri_api::dialog::{save, SaveDialogOptions};
///
/// let file = save(None).await;
/// ```
/// @param options Dialog options.
/// @returns File path, or `None` if user cancelled the dialog.
pub async fn save(options: Option<SaveDialogOptions>) -> crate::Result<Option<PathBuf>> {
let path = inner::save(serde_wasm_bindgen::to_value(&options)?).await?;
Ok(serde_wasm_bindgen::from_value(path)?) // Ok(serde_wasm_bindgen::from_value(js_val)?)
} // }
// /// Shows a message dialog with an `Ok` button.
// ///
// /// # Example
// ///
// /// ```rust,no_run
// /// use tauri_api::dialog::{message, MessageDialogOptions};
// ///
// /// message("Tauri is awesome", None).await;
// /// ```
// /// @param message Message to display.
// /// @param options Dialog options.
// /// @returns Promise resolved when user closes the dialog.
// pub async fn message(message: &str, options: Option<MessageDialogOptions>) -> crate::Result<()> {
// Ok(inner::message(message, serde_wasm_bindgen::to_value(&options)?).await?)
// }
// /// Opens a file/directory selection dialog for a single file.
// /// `multiple` field of [`options`](OpenDialogOptions) must be `false`, if provided.
// ///
// /// The selected paths are added to the filesystem and asset protocol allowlist scopes.
// /// When security is mroe important than the ease of use of this API,
// /// prefer writing a dedicated command instead.
// ///
// /// Note that the allowlist scope change is not persisited,
// /// so the values are cleared when the applicaiton is restarted.
// /// You can save it to the filessytem using the [tauri-plugin-persisted-scope](https://github.com/tauri-apps/tauri-plugin-persisted-scope).
// ///
// /// # Example
// ///
// /// ```rust,no_run
// /// use tauri_api::dialog::{open, OpenDialogOptions};
// ///
// /// let file = open(None).await;
// ///
// /// let mut opts = OpenDialogOptions::new();
// /// opts.directory = true;
// /// let dir = open(Some(opts)).await;
// /// ```
// /// @param options Dialog options.
// /// @returns List of file paths, or `None` if user cancelled the dialog.
// pub async fn open(options: Option<OpenDialogOptions>) -> crate::Result<Option<PathBuf>> {
// let file = inner::open(serde_wasm_bindgen::to_value(&options)?).await?;
// Ok(serde_wasm_bindgen::from_value(file)?)
// }
// /// Opens a file/directory selection dialog for multiple files.
// /// `multiple` field of [`options`](OpenDialogOptions) must be `true`, if provided.
// ///
// /// The selected paths are added to the filesystem and asset protocol allowlist scopes.
// /// When security is mroe important than the ease of use of this API,
// /// prefer writing a dedicated command instead.
// ///
// /// Note that the allowlist scope change is not persisited,
// /// so the values are cleared when the applicaiton is restarted.
// /// You can save it to the filessytem using the [tauri-plugin-persisted-scope](https://github.com/tauri-apps/tauri-plugin-persisted-scope).
// ///
// /// # Example
// ///
// /// ```rust,no_run
// /// use tauri_api::dialog::{open, OpenDialogOptions};
// ///
// /// let files = open_multiple(None).await;
// ///
// /// let mut opts = OpenDialogOptions::new();
// /// opts.multiple = true;
// /// opts.directory = true;
// /// let dirs = open(Some(opts)).await;
// /// ```
// /// @param options Dialog options.
// /// @returns List of file paths, or `None` if user cancelled the dialog.
// pub async fn open_multiple(
// options: Option<OpenDialogOptions>,
// ) -> crate::Result<Option<Vec<PathBuf>>> {
// let files = inner::open_multiple(serde_wasm_bindgen::to_value(&options)?).await?;
// Ok(serde_wasm_bindgen::from_value(files)?)
// }
// /// Opens a file/directory save dialog.
// ///
// /// The selected paths are added to the filesystem and asset protocol allowlist scopes.
// /// When security is mroe important than the ease of use of this API,
// /// prefer writing a dedicated command instead.
// ///
// /// Note that the allowlist scope change is not persisited,
// /// so the values are cleared when the applicaiton is restarted.
// /// You can save it to the filessytem using the [tauri-plugin-persisted-scope](https://github.com/tauri-apps/tauri-plugin-persisted-scope).
// ///
// /// # Example
// ///
// /// ```rust,no_run
// /// use tauri_api::dialog::{save, SaveDialogOptions};
// ///
// /// let file = save(None).await;
// /// ```
// /// @param options Dialog options.
// /// @returns File path, or `None` if user cancelled the dialog.
// pub async fn save(options: Option<SaveDialogOptions>) -> crate::Result<Option<PathBuf>> {
// let path = inner::save(serde_wasm_bindgen::to_value(&options)?).await?;
// Ok(serde_wasm_bindgen::from_value(path)?)
// }
mod inner { mod inner {
use wasm_bindgen::{prelude::wasm_bindgen, JsValue}; use wasm_bindgen::{prelude::wasm_bindgen, JsValue};
@ -275,8 +597,6 @@ mod inner {
#[wasm_bindgen(catch)] #[wasm_bindgen(catch)]
pub async fn open(options: JsValue) -> Result<JsValue, JsValue>; pub async fn open(options: JsValue) -> Result<JsValue, JsValue>;
#[wasm_bindgen(catch)] #[wasm_bindgen(catch)]
pub async fn open_multiple(options: JsValue) -> Result<JsValue, JsValue>;
#[wasm_bindgen(catch)]
pub async fn message(message: &str, option: JsValue) -> Result<(), JsValue>; pub async fn message(message: &str, option: JsValue) -> Result<(), JsValue>;
#[wasm_bindgen(catch)] #[wasm_bindgen(catch)]
pub async fn save(options: JsValue) -> Result<JsValue, JsValue>; pub async fn save(options: JsValue) -> Result<JsValue, JsValue>;