use ratatui::layout::Rect; use ratatui::style::{Style, Modifier}; use ratatui::text::{Line, Span}; use ratatui::widgets::Block; use ratatui::Frame; use super::theme::Theme; pub fn draw_status_bar(frame: &mut Frame, area: Rect, state: &crate::app::state::rest::AppStateRest) { // Connection status — reflects actual agent readiness: // PROG → turn is in flight // READY → connected and ready // NOAPI → disconnected let spinner_frames = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"]; let (agent_status, conn_color) = if state.turn_in_flight() { let frame = spinner_frames[(state.misc.tick_count as usize / 2) % spinner_frames.len()]; (format!("{} PROG", frame), Theme::MODE_YOLO) } else if state.misc.api_connected { ("READY".to_string(), Theme::MODE_AUTO) } else { ("NOAPI".to_string(), Theme::DIM) }; let status = Span::styled( format!(" {} ", agent_status), Style::default() .fg(if agent_status == "NOAPI" { Theme::DIM } else { Theme::BG }) .bg(conn_color) .add_modifier(Modifier::BOLD), ); // Left chunk: [zesdex] STATUS let mut spans = vec![ Span::styled(" [zesdex] ", Style::default().fg(Theme::TEXT).add_modifier(Modifier::BOLD)), status, ]; // Right chunk: provider · model spans.push(Span::styled( format!(" {} · {} ", state.settings.provider, state.settings.model), Style::default().fg(Theme::DIM), )); let line = Line::from(spans); let block = Block::default() .style( Style::default() .bg(Theme::STATUS_BAR_BG) .fg(Theme::TEXT), ); let paragraph = ratatui::widgets::Paragraph::new(line).block(block); frame.render_widget(paragraph, area); }