1use ratatui::buffer::Buffer;
7use ratatui::layout::{Alignment, Constraint, Direction, Layout, Rect};
8use ratatui::style::{Modifier, Style};
9use ratatui::text::{Line, Span};
10use ratatui::widgets::{Paragraph, Widget};
11
12use crate::app::App;
13use crate::triptych::Pane;
14
15pub fn draw(f: &mut ratatui::Frame<'_>, area: Rect, app: &App) {
16 Statusline { app }.render(area, f.buffer_mut());
17}
18
19pub struct Statusline<'a> {
20 pub app: &'a App,
21}
22
23impl Widget for Statusline<'_> {
24 fn render(self, area: Rect, buf: &mut Buffer) {
25 let muted = Style::default().fg(self.app.capabilities.muted());
26 if matches!(self.app.stage, crate::app::Stage::StreamKeys) {
34 let target_id = self
35 .app
36 .selected_agent_id()
37 .unwrap_or_else(|| "<no agent>".into());
38 let target = crate::data::agent_label(&self.app.team, &target_id);
39 let banner = format!(
40 "● STREAM-KEYS → {target} keystrokes forwarding to tmux pane · Esc to exit"
41 );
42 let style = Style::default()
43 .fg(self.app.capabilities.accent())
44 .add_modifier(Modifier::REVERSED | Modifier::BOLD);
45 Paragraph::new(banner)
46 .style(style)
47 .alignment(Alignment::Left)
48 .render(area, buf);
49 return;
50 }
51 let tab_hint = Span::styled(
58 "Tab cycle panes",
59 Style::default()
60 .fg(self.app.capabilities.accent())
61 .add_modifier(Modifier::BOLD),
62 );
63 let sep = Span::styled(" · ", muted);
64
65 let contextual = match self.app.focused_pane {
66 Pane::Roster => "/ search · ⏎ open · @ send · q quit",
67 Pane::Detail => "Ctrl+E stream keys · / filter · w wall · @ send · q quit",
71 Pane::Mailbox => "← / → tabs · ⏎ open · ! broadcast · q quit",
72 };
73
74 let left = Line::from(vec![tab_hint, sep, Span::styled(contextual, muted)]);
75
76 let right = "? help · t tutorial";
78
79 let cols = Layout::default()
80 .direction(Direction::Horizontal)
81 .constraints([
82 Constraint::Min(0),
83 Constraint::Length(right.len() as u16 + 1),
84 ])
85 .split(area);
86
87 Paragraph::new(left)
88 .alignment(Alignment::Left)
89 .render(cols[0], buf);
90 Paragraph::new(right)
91 .style(muted)
92 .alignment(Alignment::Right)
93 .render(cols[1], buf);
94 }
95}