use crate::AppModel;
use crate::boundary::reply::Reply;
use crate::boundary::{Gesture, Query, codec};
use crate::registry::roster::ClientRow;
use crate::theme;
pub fn section(ui: &mut egui::Ui, model: &mut AppModel) {
let Some(ws) = model.focused_workspace() else {
return;
};
let question = codec::encode(&Gesture::Ask(Query::Clients {
workspace: crate::naming::leaf(&ws),
}));
let (rows, refused) = match model.wire_ask(&question) {
Some(Ok(Reply::Clients(rows))) => (rows, None),
Some(Err(said)) => (Vec::new(), Some(said)),
Some(Ok(_)) | None => (Vec::new(), None),
};
if rows.is_empty() && refused.is_none() {
return;
}
let collapsed = model.is_collapsed("clients");
let arrow = if collapsed { "▶" } else { "▼" };
if ui
.selectable_label(false, format!("{arrow} clients"))
.on_hover_text(
"show or hide the clients section — the machines registered in this workspace, \
whether each is connected right now, and the tools each one offers. Read over the \
wire, like every seat's: the same rows are `/clients`.",
)
.clicked()
{
model.set_collapsed("clients", !collapsed);
}
if collapsed {
return;
}
ui.indent("clients", |ui| {
if let Some(said) = &refused {
ui.colored_label(theme::ICHOR, said);
}
for row in &rows {
client_row(ui, row);
}
});
}
fn client_row(ui: &mut egui::Ui, row: &ClientRow) {
let (glyph, hue, says) = if row.present {
("●", theme::HYDRA, "connected right now")
} else {
("○", theme::ASH, "registered, not connected")
};
ui.horizontal(|ui| {
ui.colored_label(hue, glyph).on_hover_text(says);
ui.label(&row.client);
})
.response
.on_hover_text(says);
ui.indent(&row.client, |ui| {
if row.tools.is_empty() {
ui.weak("no tools advertised");
}
for tool in &row.tools {
ui.weak(&tool.name).on_hover_text(&tool.description);
}
});
}