use egui::{Context, Id, Modal, RichText, ScrollArea};
use crate::icons::material_design_icons::{MDI_ALERT_CIRCLE_OUTLINE, MDI_CONTENT_COPY};
use crate::state::AppState;
use henad_compute::fault::{BUILDING, FaultKind};
const MAX_MESSAGE_HEIGHT: f32 = 220.0;
pub fn fault_modal(ctx: &Context, app: &mut AppState) {
let Some(shown) = &app.fault else {
return;
};
let fault = &shown.fault;
let title = if fault.during == BUILDING {
"Model build failed"
} else {
"Simulation aborted"
};
let subject = shown.model.as_deref().unwrap_or("Model");
let lead = match &fault.kind {
FaultKind::Panic { location: Some(at), .. } => {
format!("{subject} panicked while {}, at {at}.", fault.during)
}
FaultKind::Panic { location: None, .. } => format!("{subject} panicked while {}.", fault.during),
FaultKind::Refused(_) => format!("{subject} cannot run on this device."),
FaultKind::DeviceLost => format!("GPU device was lost while {} for {subject}.", fault.during),
_ => format!("GPU reported an error while {} for {subject}.", fault.during),
};
let detail = match &fault.kind {
FaultKind::Device(error) => error.to_string(),
FaultKind::Poll(error) => error.to_string(),
FaultKind::Panic { message, .. } | FaultKind::Refused(message) => message.clone(),
_ => fault.to_string(),
};
let mut dismissed = false;
let response = Modal::new(Id::new("henad_fault_modal")).show(ctx, |ui| {
ui.set_max_width(560.0);
ui.horizontal(|ui| {
ui.colored_label(
ui.visuals().error_fg_color,
RichText::new(MDI_ALERT_CIRCLE_OUTLINE).heading(),
);
ui.heading(title);
});
ui.add_space(4.0);
ui.label(lead);
ui.add_space(8.0);
ScrollArea::vertical().max_height(MAX_MESSAGE_HEIGHT).show(ui, |ui| {
ui.add(egui::Label::new(RichText::new(&detail).monospace()).selectable(true));
});
ui.add_space(8.0);
ui.separator();
ui.horizontal(|ui| {
if ui
.button(format!("{MDI_CONTENT_COPY} Copy"))
.on_hover_text("Copy message to clipboard")
.clicked()
{
ui.ctx().copy_text(detail.clone());
}
if ui.button("Dismiss").clicked() {
dismissed = true;
}
});
});
if dismissed || response.should_close() {
app.fault = None;
}
}