use std::cell::RefCell;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum DialogType {
Alert,
Confirm,
Prompt,
BeforeUnload,
}
impl DialogType {
pub fn as_str(&self) -> &'static str {
match self {
DialogType::Alert => "alert",
DialogType::Confirm => "confirm",
DialogType::Prompt => "prompt",
DialogType::BeforeUnload => "beforeunload",
}
}
pub fn from_str(s: &str) -> Self {
match s {
"confirm" => DialogType::Confirm,
"prompt" => DialogType::Prompt,
"beforeunload" => DialogType::BeforeUnload,
_ => DialogType::Alert, }
}
}
pub struct Dialog {
dialog_type: DialogType,
message: RefCell<String>,
default_value: RefCell<Option<String>>,
closed: RefCell<bool>,
}
impl std::fmt::Debug for Dialog {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Dialog")
.field("dialog_type", &self.dialog_type)
.field("message", &self.message.borrow())
.field("default_value", &self.default_value.borrow())
.field("closed", &self.closed.borrow())
.finish()
}
}
impl Dialog {
pub fn new(
dialog_type: DialogType,
message: impl Into<String>,
default_value: Option<String>,
) -> Self {
Self {
dialog_type,
message: RefCell::new(message.into()),
default_value: RefCell::new(default_value),
closed: RefCell::new(false),
}
}
pub fn dialog_type(&self) -> DialogType {
self.dialog_type
}
pub fn type_str(&self) -> &'static str {
self.dialog_type.as_str()
}
pub fn message(&self) -> String {
self.message.borrow().clone()
}
pub fn default_value(&self) -> Option<String> {
self.default_value.borrow().clone()
}
pub fn set_default_value(&self, v: impl Into<String>) {
*self.default_value.borrow_mut() = Some(v.into());
}
pub fn is_closed(&self) -> bool {
*self.closed.borrow()
}
pub fn set_closed(&self) {
*self.closed.borrow_mut() = true;
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn alert_dialog_basic() {
let d = Dialog::new(DialogType::Alert, "Hello", None);
assert_eq!(d.dialog_type(), DialogType::Alert);
assert_eq!(d.type_str(), "alert");
assert_eq!(d.message(), "Hello");
assert!(d.default_value().is_none());
assert!(!d.is_closed());
}
#[test]
fn prompt_dialog_with_default() {
let d = Dialog::new(DialogType::Prompt, "Name?", Some("Alice".into()));
assert_eq!(d.dialog_type(), DialogType::Prompt);
assert_eq!(d.type_str(), "prompt");
assert_eq!(d.default_value(), Some("Alice".into()));
}
#[test]
fn confirm_dialog_no_default() {
let d = Dialog::new(DialogType::Confirm, "Are you sure?", None);
assert_eq!(d.dialog_type(), DialogType::Confirm);
assert_eq!(d.type_str(), "confirm");
assert!(d.default_value().is_none());
}
#[test]
fn beforeunload_dialog() {
let d = Dialog::new(DialogType::BeforeUnload, "", None);
assert_eq!(d.type_str(), "beforeunload");
}
#[test]
fn closed_flag() {
let d = Dialog::new(DialogType::Alert, "x", None);
assert!(!d.is_closed());
d.set_closed();
assert!(d.is_closed());
}
#[test]
fn set_default_value_updates() {
let d = Dialog::new(DialogType::Prompt, "?", None);
assert!(d.default_value().is_none());
d.set_default_value("new");
assert_eq!(d.default_value(), Some("new".into()));
}
#[test]
fn from_str_round_trip() {
assert_eq!(DialogType::from_str("alert"), DialogType::Alert);
assert_eq!(DialogType::from_str("confirm"), DialogType::Confirm);
assert_eq!(DialogType::from_str("prompt"), DialogType::Prompt);
assert_eq!(
DialogType::from_str("beforeunload"),
DialogType::BeforeUnload
);
assert_eq!(DialogType::from_str("garbage"), DialogType::Alert);
}
}