use std::collections::{HashMap, VecDeque};
pub struct ModalRequest {
pub id: String,
pub title: String,
pub body: String,
pub confirm_text: String,
pub cancel_text: String,
pub(crate) kind: ModalRequestKind,
}
pub(crate) enum ModalRequestKind {
Confirm,
TextInput { default_text: String },
}
pub enum ModalResult {
Confirmed,
Cancelled,
TextInput(String),
}
pub(crate) enum ModalKind {
Confirm,
TextInput { current_text: String },
}
pub(crate) struct ModalData {
pub(crate) id: String,
pub(crate) title: String,
pub(crate) body: String,
pub(crate) confirm_text: String,
pub(crate) cancel_text: String,
pub(crate) kind: ModalKind,
}
#[derive(Default)]
pub struct Modals {
pub(crate) active: Option<ModalData>,
pub(crate) pending_requests: VecDeque<ModalRequest>,
results: HashMap<String, ModalResult>,
}
impl Modals {
pub fn show_confirm(
&mut self,
id: impl Into<String>,
title: impl Into<String>,
body: impl Into<String>,
) {
self.pending_requests.push_back(ModalRequest {
id: id.into(),
title: title.into(),
body: body.into(),
confirm_text: "Confirm".to_string(),
cancel_text: "Cancel".to_string(),
kind: ModalRequestKind::Confirm,
});
}
pub fn show_confirm_with_text(
&mut self,
id: impl Into<String>,
title: impl Into<String>,
body: impl Into<String>,
confirm_text: impl Into<String>,
cancel_text: impl Into<String>,
) {
self.pending_requests.push_back(ModalRequest {
id: id.into(),
title: title.into(),
body: body.into(),
confirm_text: confirm_text.into(),
cancel_text: cancel_text.into(),
kind: ModalRequestKind::Confirm,
});
}
pub fn show_text_input(
&mut self,
id: impl Into<String>,
title: impl Into<String>,
prompt: impl Into<String>,
default_text: impl Into<String>,
) {
self.pending_requests.push_back(ModalRequest {
id: id.into(),
title: title.into(),
body: prompt.into(),
confirm_text: "OK".to_string(),
cancel_text: "Cancel".to_string(),
kind: ModalRequestKind::TextInput {
default_text: default_text.into(),
},
});
}
pub fn show_text_input_with_text(
&mut self,
id: impl Into<String>,
title: impl Into<String>,
prompt: impl Into<String>,
default_text: impl Into<String>,
confirm_text: impl Into<String>,
cancel_text: impl Into<String>,
) {
self.pending_requests.push_back(ModalRequest {
id: id.into(),
title: title.into(),
body: prompt.into(),
confirm_text: confirm_text.into(),
cancel_text: cancel_text.into(),
kind: ModalRequestKind::TextInput {
default_text: default_text.into(),
},
});
}
pub fn take_result(&mut self, id: &str) -> Option<ModalResult> {
self.results.remove(id)
}
pub fn has_open_modal(&self) -> bool {
self.active.is_some()
}
pub(crate) fn store_result(&mut self, id: String, result: ModalResult) {
self.results.insert(id, result);
}
pub(crate) fn activate_next_pending(&mut self) {
if self.active.is_none() {
let Some(request) = self.pending_requests.pop_front() else {
return;
};
let kind = match request.kind {
ModalRequestKind::Confirm => ModalKind::Confirm,
ModalRequestKind::TextInput { default_text } => ModalKind::TextInput {
current_text: default_text,
},
};
self.active = Some(ModalData {
id: request.id,
title: request.title,
body: request.body,
confirm_text: request.confirm_text,
cancel_text: request.cancel_text,
kind,
});
}
}
}