Skip to main content

mobiler_core/
dialog.rs

1//! Labels for the built-in confirm dialog and date/time pickers, so an app can word the buttons in
2//! its own language and say what they do ("Cancel booking" / "Keep it") instead of a generic
3//! OK / Cancel. Used with [`Cx::confirm_with`](crate::Cx::confirm_with),
4//! [`Cx::pick_date_with`](crate::Cx::pick_date_with) and
5//! [`Cx::pick_time_with`](crate::Cx::pick_time_with).
6
7use serde::Serialize;
8
9/// A confirm dialog: title and message, optionally the two button labels, and whether the
10/// confirming action is destructive (danger colour on Android and web, `.destructive` on iOS).
11/// Unset labels keep the shell defaults (`OK` / `Cancel`).
12#[derive(Debug, Clone, PartialEq, Serialize)]
13pub struct Confirm {
14    title: String,
15    message: String,
16    #[serde(skip_serializing_if = "Option::is_none")]
17    confirm_label: Option<String>,
18    #[serde(skip_serializing_if = "Option::is_none")]
19    cancel_label: Option<String>,
20    #[serde(skip_serializing_if = "std::ops::Not::not")]
21    destructive: bool,
22}
23
24impl Confirm {
25    #[must_use]
26    pub fn new(title: impl Into<String>, message: impl Into<String>) -> Self {
27        Self { title: title.into(), message: message.into(), confirm_label: None, cancel_label: None, destructive: false }
28    }
29
30    /// The confirming button — name the action ("Cancel booking"), not "OK".
31    #[must_use]
32    pub fn confirm_label(mut self, label: impl Into<String>) -> Self {
33        self.confirm_label = Some(label.into());
34        self
35    }
36
37    /// The dismissing button — the way out ("Keep it").
38    #[must_use]
39    pub fn cancel_label(mut self, label: impl Into<String>) -> Self {
40        self.cancel_label = Some(label.into());
41        self
42    }
43
44    /// The confirming action destroys something: the shells draw it in the danger style.
45    #[must_use]
46    pub fn destructive(mut self) -> Self {
47        self.destructive = true;
48        self
49    }
50
51    pub(crate) fn to_input(&self) -> String {
52        serde_json::to_string(self).expect("serialize confirm")
53    }
54}
55
56/// Labels for the native date/time picker; unset ones keep the shell defaults. The web shell opens
57/// the browser's own picker, which draws its chrome in the browser's language and ignores these.
58#[derive(Debug, Clone, Default, PartialEq, Serialize)]
59pub struct Picker {
60    #[serde(skip_serializing_if = "Option::is_none")]
61    title: Option<String>,
62    #[serde(skip_serializing_if = "Option::is_none")]
63    confirm_label: Option<String>,
64    #[serde(skip_serializing_if = "Option::is_none")]
65    cancel_label: Option<String>,
66}
67
68impl Picker {
69    #[must_use]
70    pub fn new() -> Self {
71        Self::default()
72    }
73
74    /// The picker's title — shown as the iOS action sheet title. Android sets it as the dialog
75    /// title, but the Material date/time picker on current API levels doesn't display it; the web
76    /// picker ignores it.
77    #[must_use]
78    pub fn title(mut self, title: impl Into<String>) -> Self {
79        self.title = Some(title.into());
80        self
81    }
82
83    /// The button that accepts the picked value.
84    #[must_use]
85    pub fn confirm_label(mut self, label: impl Into<String>) -> Self {
86        self.confirm_label = Some(label.into());
87        self
88    }
89
90    /// The button that dismisses the picker without a value.
91    #[must_use]
92    pub fn cancel_label(mut self, label: impl Into<String>) -> Self {
93        self.cancel_label = Some(label.into());
94        self
95    }
96
97    pub(crate) fn to_input(&self) -> String {
98        serde_json::to_string(self).expect("serialize picker")
99    }
100}