diff --git a/.changes/native-dialog-button-text.md b/.changes/native-dialog-button-text.md new file mode 100644 index 000000000..5440cea1d --- /dev/null +++ b/.changes/native-dialog-button-text.md @@ -0,0 +1,5 @@ +--- +"dialog": patch:breaking +--- + +Changed `MessageDialogBuilder::ok_button_label` and `MessageDialogBuilder::cancel_button_label` to `MessageDialogBuilder::buttons` which takes an enum now diff --git a/plugins/dialog/src/commands.rs b/plugins/dialog/src/commands.rs index 9173e83e9..8690a8b02 100644 --- a/plugins/dialog/src/commands.rs +++ b/plugins/dialog/src/commands.rs @@ -8,7 +8,10 @@ use serde::{Deserialize, Serialize}; use tauri::{command, Manager, Runtime, State, Window}; use tauri_plugin_fs::FsExt; -use crate::{Dialog, FileDialogBuilder, FilePath, MessageDialogKind, Result}; +use crate::{ + Dialog, FileDialogBuilder, FilePath, MessageDialogButtons, MessageDialogKind, Result, CANCEL, + OK, +}; #[derive(Serialize)] #[serde(untagged)] @@ -244,11 +247,12 @@ fn message_dialog( title: Option, message: String, kind: Option, - ok_button_label: Option, - cancel_button_label: Option, + buttons: MessageDialogButtons, ) -> bool { let mut builder = dialog.message(message); + builder = builder.buttons(buttons); + if let Some(title) = title { builder = builder.title(title); } @@ -262,14 +266,6 @@ fn message_dialog( builder = builder.kind(kind); } - if let Some(ok) = ok_button_label { - builder = builder.ok_button_label(ok); - } - - if let Some(cancel) = cancel_button_label { - builder = builder.cancel_button_label(cancel); - } - builder.blocking_show() } @@ -288,8 +284,11 @@ pub(crate) async fn message( title, message, kind, - ok_button_label, - None, + if let Some(ok_button_label) = ok_button_label { + MessageDialogButtons::OkCustom(ok_button_label) + } else { + MessageDialogButtons::Ok + }, )) } @@ -309,8 +308,7 @@ pub(crate) async fn ask( title, message, kind, - Some(ok_button_label.unwrap_or_else(|| "Yes".into())), - Some(cancel_button_label.unwrap_or_else(|| "No".into())), + get_ok_cancel_type(ok_button_label, cancel_button_label), )) } @@ -330,7 +328,22 @@ pub(crate) async fn confirm( title, message, kind, - Some(ok_button_label.unwrap_or_else(|| "Ok".into())), - Some(cancel_button_label.unwrap_or_else(|| "Cancel".into())), + get_ok_cancel_type(ok_button_label, cancel_button_label), )) } + +fn get_ok_cancel_type( + ok_button_label: Option, + cancel_button_label: Option, +) -> MessageDialogButtons { + if let Some(ok_button_label) = ok_button_label { + MessageDialogButtons::OkCancelCustom( + ok_button_label, + cancel_button_label.unwrap_or(CANCEL.to_string()), + ) + } else if let Some(cancel_button_label) = cancel_button_label { + MessageDialogButtons::OkCancelCustom(OK.to_string(), cancel_button_label) + } else { + MessageDialogButtons::OkCancel + } +} diff --git a/plugins/dialog/src/desktop.rs b/plugins/dialog/src/desktop.rs index be19b49a9..d30f6bfee 100644 --- a/plugins/dialog/src/desktop.rs +++ b/plugins/dialog/src/desktop.rs @@ -13,9 +13,7 @@ use rfd::{AsyncFileDialog, AsyncMessageDialog}; use serde::de::DeserializeOwned; use tauri::{plugin::PluginApi, AppHandle, Runtime}; -use crate::{models::*, FileDialogBuilder, FilePath, MessageDialogBuilder}; - -const OK: &str = "Ok"; +use crate::{models::*, FileDialogBuilder, FilePath, MessageDialogBuilder, OK}; pub fn init( app: &AppHandle, @@ -109,22 +107,24 @@ impl From> for AsyncFileDialog { } } +impl From for rfd::MessageButtons { + fn from(value: MessageDialogButtons) -> Self { + match value { + MessageDialogButtons::Ok => Self::Ok, + MessageDialogButtons::OkCancel => Self::OkCancel, + MessageDialogButtons::OkCustom(ok) => Self::OkCustom(ok), + MessageDialogButtons::OkCancelCustom(ok, cancel) => Self::OkCancelCustom(ok, cancel), + } + } +} + impl From> for AsyncMessageDialog { fn from(d: MessageDialogBuilder) -> Self { let mut dialog = AsyncMessageDialog::new() .set_title(&d.title) .set_description(&d.message) - .set_level(d.kind.into()); - - let buttons = match (d.ok_button_label, d.cancel_button_label) { - (Some(ok), Some(cancel)) => Some(rfd::MessageButtons::OkCancelCustom(ok, cancel)), - (Some(ok), None) => Some(rfd::MessageButtons::OkCustom(ok)), - (None, Some(cancel)) => Some(rfd::MessageButtons::OkCancelCustom(OK.into(), cancel)), - (None, None) => None, - }; - if let Some(buttons) = buttons { - dialog = dialog.set_buttons(buttons); - } + .set_level(d.kind.into()) + .set_buttons(d.buttons.into()); if let Some(parent) = d.parent { dialog = dialog.set_parent(&parent); @@ -213,7 +213,11 @@ pub fn show_message_dialog( ) { use rfd::MessageDialogResult; - let ok_label = dialog.ok_button_label.clone(); + let ok_label = match &dialog.buttons { + MessageDialogButtons::OkCustom(ok) => Some(ok.clone()), + MessageDialogButtons::OkCancelCustom(ok, _) => Some(ok.clone()), + _ => None, + }; let f = move |res| { f(match res { MessageDialogResult::Ok | MessageDialogResult::Yes => true, diff --git a/plugins/dialog/src/lib.rs b/plugins/dialog/src/lib.rs index 5f2b35b02..a7538e1b1 100644 --- a/plugins/dialog/src/lib.rs +++ b/plugins/dialog/src/lib.rs @@ -41,6 +41,9 @@ use desktop::*; #[cfg(mobile)] use mobile::*; +pub(crate) const OK: &str = "Ok"; +pub(crate) const CANCEL: &str = "Cancel"; + macro_rules! blocking_fn { ($self:ident, $fn:ident) => {{ let (tx, rx) = sync_channel(0); @@ -89,14 +92,13 @@ impl Dialog { /// - Ask dialog: /// /// ``` - /// use tauri_plugin_dialog::DialogExt; + /// use tauri_plugin_dialog::{DialogExt, MessageDialogButtons}; /// /// tauri::Builder::default() /// .setup(|app| { /// app.dialog() /// .message("Are you sure?") - /// .ok_button_label("Yes") - /// .cancel_button_label("No") + /// .buttons(MessageDialogButtons::OkCancelCustom("Yes", "No")) /// .show(|yes| { /// println!("user said {}", if yes { "yes" } else { "no" }); /// }); @@ -107,13 +109,13 @@ impl Dialog { /// - Message dialog with OK button: /// /// ``` - /// use tauri_plugin_dialog::DialogExt; + /// use tauri_plugin_dialog::{DialogExt, MessageDialogButtons}; /// /// tauri::Builder::default() /// .setup(|app| { /// app.dialog() /// .message("Job completed successfully") - /// .ok_button_label("Ok") + /// .buttons(MessageDialogButtons::Ok) /// .show(|_| { /// println!("dialog closed"); /// }); @@ -129,7 +131,7 @@ impl Dialog { /// but note that it cannot be executed on the main thread as it will freeze your application. /// /// ``` - /// use tauri_plugin_dialog::DialogExt; + /// use tauri_plugin_dialog::{DialogExt, MessageDialogButtons}; /// /// tauri::Builder::default() /// .setup(|app| { @@ -137,8 +139,7 @@ impl Dialog { /// std::thread::spawn(move || { /// let yes = handle.dialog() /// .message("Are you sure?") - /// .ok_button_label("Yes") - /// .cancel_button_label("No") + /// .buttons(MessageDialogButtons::OkCancelCustom("Yes", "No")) /// .blocking_show(); /// }); /// @@ -196,8 +197,7 @@ pub struct MessageDialogBuilder { pub(crate) title: String, pub(crate) message: String, pub(crate) kind: MessageDialogKind, - pub(crate) ok_button_label: Option, - pub(crate) cancel_button_label: Option, + pub(crate) buttons: MessageDialogButtons, #[cfg(desktop)] pub(crate) parent: Option, } @@ -210,8 +210,8 @@ pub(crate) struct MessageDialogPayload<'a> { title: &'a String, message: &'a String, kind: &'a MessageDialogKind, - ok_button_label: &'a Option, - cancel_button_label: &'a Option, + ok_button_label: Option<&'a str>, + cancel_button_label: Option<&'a str>, } // raw window handle :( @@ -225,8 +225,7 @@ impl MessageDialogBuilder { title: title.into(), message: message.into(), kind: Default::default(), - ok_button_label: None, - cancel_button_label: None, + buttons: Default::default(), #[cfg(desktop)] parent: None, } @@ -234,12 +233,20 @@ impl MessageDialogBuilder { #[cfg(mobile)] pub(crate) fn payload(&self) -> MessageDialogPayload<'_> { + let (ok_button_label, cancel_button_label) = match &self.buttons { + MessageDialogButtons::Ok => (Some(OK), None), + MessageDialogButtons::OkCancel => (Some(OK), Some(CANCEL)), + MessageDialogButtons::OkCustom(ok) => (Some(ok.as_str()), Some(CANCEL)), + MessageDialogButtons::OkCancelCustom(ok, cancel) => { + (Some(ok.as_str()), Some(cancel.as_str())) + } + }; MessageDialogPayload { title: &self.title, message: &self.message, kind: &self.kind, - ok_button_label: &self.ok_button_label, - cancel_button_label: &self.cancel_button_label, + ok_button_label, + cancel_button_label, } } @@ -266,15 +273,9 @@ impl MessageDialogBuilder { self } - /// Sets the label for the OK button. - pub fn ok_button_label(mut self, label: impl Into) -> Self { - self.ok_button_label.replace(label.into()); - self - } - - /// Sets the label for the Cancel button. - pub fn cancel_button_label(mut self, label: impl Into) -> Self { - self.cancel_button_label.replace(label.into()); + /// Sets the dialog buttons. + pub fn buttons(mut self, buttons: MessageDialogButtons) -> Self { + self.buttons = buttons; self } diff --git a/plugins/dialog/src/models.rs b/plugins/dialog/src/models.rs index fa9224e18..3f9eb6c13 100644 --- a/plugins/dialog/src/models.rs +++ b/plugins/dialog/src/models.rs @@ -49,3 +49,18 @@ impl Serialize for MessageDialogKind { } } } + +/// Set of button that will be displayed on the dialog +#[non_exhaustive] +#[derive(Debug, Default, Clone)] +pub enum MessageDialogButtons { + #[default] + /// A single `Ok` button with OS default dialog text + Ok, + /// 2 buttons `Ok` and `Cancel` with OS default dialog texts + OkCancel, + /// A single `Ok` button with custom text + OkCustom(String), + /// 2 buttons `Ok` and `Cancel` with custom texts + OkCancelCustom(String, String), +}