use crate::reply::roster::WsRow;
use crate::ui::{Aim, Chunk, Model, theme};
pub const NO_CHANNEL: &str = "no channel provisioned — material arrives by hand";
pub const NO_NAME_HERE: &str = "this seat holds no name for it";
pub const HEADING: &str = "channels";
pub fn aimable(model: &Model) -> Vec<Aim> {
let mut rows = Vec::new();
for chunk in &model.roster {
for row in ordered(&chunk.walls) {
if let Some(address) = chunk.channel.address(&row) {
rows.push(Aim {
channel: chunk.channel.name.clone(),
address,
});
}
}
}
rows
}
pub fn render(ui: &mut egui::Ui, model: &mut Model) {
ui.heading(crate::ui::keys::heading(
HEADING,
model.focus == crate::ui::Pane::Roster,
));
if model.roster.is_empty() {
ui.label(NO_CHANNEL);
return;
}
for chunk in model.roster.clone() {
section(ui, model, &chunk);
}
}
fn section(ui: &mut egui::Ui, model: &mut Model, chunk: &Chunk) {
ui.separator();
ui.label(header(chunk));
for note in [chunk.stale.as_ref(), chunk.growth.as_ref()]
.into_iter()
.flatten()
{
ui.colored_label(theme::tone_ink(&crate::reply::convs::Tone::Weak), note);
}
for row in ordered(&chunk.walls) {
wall(ui, model, chunk, &row);
}
}
pub fn header(chunk: &Chunk) -> String {
match &chunk.channel.named_there {
Some(there) if *there != chunk.channel.name => {
format!("{} (named {:?} on its host)", chunk.channel.name, there)
}
_ => chunk.channel.name.clone(),
}
}
fn wall(ui: &mut egui::Ui, model: &mut Model, chunk: &Chunk, row: &WsRow) {
let Some(address) = chunk.channel.address(row) else {
ui.label(format!("{} — {NO_NAME_HERE}", line(row)));
return;
};
let aimed = model.aimed_at(&chunk.channel.name, Some(&address));
if ui.selectable_label(aimed, line(row)).clicked() {
model.aim_at(&chunk.channel.name.clone(), &address);
}
}
pub fn ordered(walls: &[WsRow]) -> Vec<WsRow> {
let mut rows = walls.to_vec();
rows.sort_by(|a, b| {
(a.pinned.unwrap_or(u64::MAX), &a.workspace)
.cmp(&(b.pinned.unwrap_or(u64::MAX), &b.workspace))
});
rows
}
pub fn line(row: &WsRow) -> String {
let mut said = vec![format!(
"{} ({}) {} conversations",
row.workspace,
row.kind.label(),
row.agents
)];
if row.attention > 0 {
said.push(format!("{} waiting", row.attention));
}
if row.running {
said.push("running".to_owned());
}
said.join(" ")
}
#[cfg(test)]
mod tests;