use crate::AppModel;
use crate::cli_outbound::Cli;
use crate::nav::convs::Selection;
use crate::theme;
use super::ShellState;
pub fn center(
ui: &mut egui::Ui,
model: &mut AppModel,
state: &mut ShellState,
lernie: &Cli,
bz: &Cli,
) {
let Some(ws) = model.focused_workspace() else {
super::bootstrap::render(ui, model, state);
return;
};
if model.focused_is_replay() {
ui.weak("replay · read-only");
}
let Some(seat) = super::seat::selection(model) else {
ui.weak("select a conversation — or start one below");
return;
};
let agent_id = seat.agent_id.clone();
let detail = super::seat::detail(model, &ws, &agent_id).value;
let agent_marks = detail
.as_ref()
.map(|view| view.marks.clone())
.unwrap_or_default();
let live = detail.map(|view| view.seats).unwrap_or_default();
let ws_balls = super::chrome::focused_balls(model);
header(ui, &seat, &live, &ws_balls);
for mark in agent_marks {
let (_, hue, phrase) = theme::mark_badge(mark);
ui.colored_label(hue, phrase);
}
let steps = super::inspector::steps(model, &ws, &agent_id)
.value
.unwrap_or_default();
let auth_failed = crate::login::auth::latest_step_auth_failed(&steps);
let wound = crate::steps_view::latest_wound(&steps);
if auth_failed.offered() {
ui.colored_label(theme::ICHOR, auth_failed.banner());
let state_root = model.state_root().to_path_buf();
super::login_pane::login_section(ui, &mut state.wall.login, bz, &state_root);
}
if state.wound_grace.paints(
&ws,
&agent_id,
wound.wounded(),
model.cadence().wound_grace(),
) {
ui.colored_label(theme::ICHOR, wound.banner());
}
if state.orphan_grace.paints(
&ws,
&agent_id,
steps.orphan.orphaned(),
model.cadence().wound_grace(),
) {
ui.colored_label(theme::ICHOR, steps.orphan.banner());
}
ui.separator();
super::inspector::tabs_and_content(ui, model, state, &ws, lernie);
}
fn header(
ui: &mut egui::Ui,
seat: &Selection,
live: &[crate::nav::convs::Seat],
ws_balls: &[crate::nav::BoundBall],
) {
let root = seat.root.as_str();
ui.horizontal(|ui| {
let heading = ui.heading(seat.name.clone());
if seat.display_only {
heading.on_hover_text(theme::NAME_DISPLAY_ONLY);
}
let started = crate::nav::convs::started_at(root);
ui.weak(started.label).on_hover_text(started.hover);
if let Some(class) = seat.flight {
let (glyph, hue, says) = theme::flight_badge(class);
let time = ui.ctx().input(|i| i.time);
ui.colored_label(theme::pulse(hue, time), format!("{glyph} {says}"));
ui.ctx().request_repaint_after(theme::PULSE_REPAINT_DELAY);
}
ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
theme::live_mark(ui, live);
});
});
if let Some(ball) = &seat.ball {
super::conv_ball::header_ball(ui, ball);
}
if !ws_balls.is_empty() {
ui.horizontal(|ui| {
ui.weak("workspace balls:");
for ball in ws_balls {
match &ball.badge {
Some(b) => ui.weak(format!("{} · {b}", ball.id)),
None => ui.weak(&ball.id),
};
}
});
}
}