use crate::AppModel;
use crate::cli_outbound::Cli;
use crate::keymap::CenterTab;
use crate::nav::menu::Seat;
use super::ShellState;
use super::menus::{BallRef, Target};
pub fn side_panel(
ui: &mut egui::Ui,
model: &mut AppModel,
state: &mut ShellState,
lernie: &Cli,
bl: &Cli,
) {
ui.style_mut().wrap_mode = Some(egui::TextWrapMode::Truncate);
super::conv_list::conversations(ui, model, state, lernie, bl);
ui.separator();
balls_section(ui, model, state, lernie, bl);
ui.separator();
for tab in [CenterTab::Config, CenterTab::Login] {
let label = format!("{}{}", entry_mark(tab), tab.label());
if ui
.selectable_label(state.center == tab, label)
.on_hover_text(tab.focus_hover())
.clicked()
{
super::center::focus(model, state, tab);
}
}
}
fn entry_mark(tab: CenterTab) -> &'static str {
match tab {
CenterTab::Config => "⚙ ",
_ => "",
}
}
fn balls_section(
ui: &mut egui::Ui,
model: &mut AppModel,
state: &mut ShellState,
lernie: &Cli,
bl: &Cli,
) {
let collapsed = model.is_collapsed("balls");
let arrow = if collapsed { "▶" } else { "▼" };
if ui
.selectable_label(false, format!("{arrow} balls"))
.on_hover_text(
"show or hide the balls section — the ready tasks you can start and the \
balls this workspace already holds (b)",
)
.clicked()
{
model.set_collapsed("balls", !collapsed);
}
if collapsed {
return;
}
ui.indent("balls", |ui| {
super::board::board(ui, model, state, lernie, bl);
if let Some(ws) = model.focused_workspace().map(std::path::Path::to_path_buf) {
for ball in model.roster_ball_rows(&ws) {
bound_ball_row(ui, model, state, lernie, bl, &ball);
}
}
});
}
fn bound_ball_row(
ui: &mut egui::Ui,
model: &mut AppModel,
state: &mut ShellState,
lernie: &Cli,
bl: &Cli,
ball: &crate::nav::BoundBall,
) {
let text = match &ball.badge {
Some(b) => format!("{} · {b}", ball.id),
None => ball.id.clone(),
};
let row = ui
.add(egui::Label::new(egui::RichText::new(text).weak()).sense(egui::Sense::click()))
.on_hover_text(
"a ball this workspace has claimed. Right-click for its actions — Close, \
Release, Move to another workspace. Each is also a key or a line: (c), \
(r), `/move [id] <to>`.",
);
let seat = Seat::BallRow {
state: ball.state,
assign_to: model.focused_ws_name(),
move_to: model.move_targets(&ball.owner),
};
let target = Target::Ball(BallRef {
project: ball.project.clone(),
id: ball.id.clone(),
owner: ball.owner.clone(),
});
super::menus::attach(&row, seat, &target, model, state, lernie, bl);
}