use super::{NO_STEPS, NOT_ANSWERED_STEPS, STEPS_HEAD, drill};
use crate::reply::steps::{StepRow, Steps};
use crate::ui::{Model, theme};
pub(super) fn half(ui: &mut egui::Ui, model: &mut Model, steps: Option<&Steps>) {
theme::paint::section(ui, STEPS_HEAD);
ui.horizontal_wrapped(|ui| match steps {
None => {
ui.label(NOT_ANSWERED_STEPS);
}
Some(listing) => {
if let Some(said) = orphaned(listing) {
ui.colored_label(theme::accent(theme::State::Annotation), said);
}
if listing.rows.is_empty() {
ui.label(NO_STEPS);
}
}
});
let Some(listing) = steps else {
return;
};
for row in &listing.rows {
step(ui, model, row);
}
}
fn step(ui: &mut egui::Ui, model: &mut Model, row: &StepRow) {
ui.horizontal_wrapped(|ui| {
ui.label(headline(row));
if let Some(weak) = provenance(row) {
ui.colored_label(theme::INK_WEAK, weak);
}
drill::control(ui, model, &row.seq);
});
let said: Vec<String> = [wounded(row), auth(row)].into_iter().flatten().collect();
if !said.is_empty() {
ui.horizontal_wrapped(|ui| {
for line in said {
ui.colored_label(theme::accent(theme::State::Annotation), line);
}
});
}
drill::records(ui, model, &row.seq);
}
pub fn orphaned(listing: &Steps) -> Option<String> {
if listing.orphan == crate::reply::steps::NONE {
return None;
}
Some(match &listing.orphan_reason {
Some(reason) => format!("an orphaned {} tail — {reason}", listing.orphan),
None => format!("an orphaned {} tail", listing.orphan),
})
}
pub fn headline(row: &StepRow) -> String {
let said = format!("{} {} — {} tokens", row.seq, row.framing, row.tokens.total);
if row.attempts > 1 {
return format!("{said}, {} attempts", row.attempts);
}
said
}
pub fn provenance(row: &StepRow) -> Option<String> {
let mut parts = Vec::new();
if let (Some(from), Some(to)) = (&row.started_at, &row.ended_at) {
parts.push(format!("{from} to {to}"));
}
if let Some(commit) = &row.commit {
parts.push(format!("at {commit}"));
}
(!parts.is_empty()).then(|| parts.join(" "))
}
pub fn wounded(row: &StepRow) -> Option<String> {
if row.wound == crate::reply::steps::NONE {
return None;
}
Some(match &row.wound_reason {
Some(reason) => format!("wound: {} — {reason}", row.wound),
None => format!("wound: {}", row.wound),
})
}
pub fn auth(row: &StepRow) -> Option<String> {
if row.wound != crate::reply::steps::REFUSED {
return None;
}
Some(match &row.auth_row {
Some(provider) => format!("a sign-in is wanted on {provider}"),
None => "a sign-in is wanted".to_owned(),
})
}