use crate::{
EditorModel, MainWindow, gui::editor::state::EditorState, settings::SettingsPersister,
};
use indicatrix::geometry::meet_solver::SolvedTier;
use indicatrix_cut_core::Design;
use slint::ComponentHandle;
use std::{cell::RefCell, rc::Rc};
use tracing::warn;
pub(super) enum StatusDecision {
Fine,
NeedsConfirm(String),
}
#[must_use]
pub(super) fn decide_write_status(
design: &Design,
solved: Result<&[SolvedTier], &str>,
) -> StatusDecision {
match solved {
Ok(solved) => {
let (message, is_problem) =
crate::gui::editor::state::status_text_and_is_problem_from_solved(design, solved);
if is_problem {
StatusDecision::NeedsConfirm(message)
} else {
StatusDecision::Fine
}
}
Err(missing) => StatusDecision::NeedsConfirm(missing.to_string()),
}
}
struct PendingWriteConfirm {
on_accept: Box<dyn FnOnce(&MainWindow)>,
suppress_key: Option<&'static str>,
}
pub(super) mod confirm_keys {
pub(in crate::gui::editor::native_io) const NOT_CLOSED_SOLID: &str =
"write_confirm.not_closed_solid";
}
fn confirm_is_suppressed(key: &str) -> bool {
SettingsPersister::installed_for_this_thread()
.is_some_and(|persister| persister.snapshot().settings.is_confirm_suppressed(key))
}
fn suppress_confirm_permanently(key: &'static str) {
let Some(persister) = SettingsPersister::installed_for_this_thread() else {
warn!("No settings persister is installed; not suppressing the prompt `{key}`");
return;
};
persister.update(|file| file.settings.suppress_confirm(key));
}
thread_local! {
static PENDING_WRITE_CONFIRM: RefCell<Option<PendingWriteConfirm>> = const { RefCell::new(None) };
}
pub(in crate::gui) fn ask_write_confirm(
ui: &MainWindow,
heading: &str,
message: String,
primary_label: &str,
suppress_key: Option<&'static str>,
on_accept: impl FnOnce(&MainWindow) + 'static,
) {
if suppress_key.is_some_and(confirm_is_suppressed) {
on_accept(ui);
return;
}
PENDING_WRITE_CONFIRM.with(|cell| {
*cell.borrow_mut() = Some(PendingWriteConfirm {
on_accept: Box::new(on_accept),
suppress_key,
});
});
let model = ui.global::<EditorModel>();
model.set_write_confirm_heading(heading.into());
model.set_write_confirm_message(message.into());
model.set_write_confirm_primary_label(primary_label.into());
model.set_write_confirm_show_dont_ask(suppress_key.is_some());
model.set_write_confirm_dont_ask(false);
model.set_write_confirm_open(true);
}
pub(super) fn setup_write_confirm_dialog_callbacks(
ui: &MainWindow,
state: &Rc<RefCell<EditorState>>,
) {
let ui_weak = ui.as_weak();
ui.global::<EditorModel>().on_write_confirm_accept(move || {
let Some(ui) = ui_weak.upgrade() else {
return;
};
let model = ui.global::<EditorModel>();
model.set_write_confirm_open(false);
let Some(pending) = PENDING_WRITE_CONFIRM.with(RefCell::take) else {
return;
};
if let Some(key) = pending.suppress_key
&& model.get_write_confirm_dont_ask()
{
suppress_confirm_permanently(key);
}
crate::gui::editor::stall_guard::stall_guard("write_confirm_accept", || {
(pending.on_accept)(&ui);
});
});
let state_cancel = Rc::clone(state);
ui.global::<EditorModel>().on_write_confirm_cancel(move || {
PENDING_WRITE_CONFIRM.with(|cell| *cell.borrow_mut() = None);
state_cancel.borrow_mut().after_save = None;
});
}