Skip to main content

stynx_code_tui/widgets/
status_bar.rs

1use ratatui::{
2    buffer::Buffer,
3    layout::Rect,
4    style::{Modifier, Style},
5    text::{Line, Span},
6    widgets::{Paragraph, Widget},
7};
8
9use crate::widgets::spinner::FRAMES;
10use crate::theme;
11
12pub struct StatusBar<'a> {
13    pub model: &'a str,
14    pub mode: &'a str,
15    pub cost: f64,
16    pub git_branch: Option<&'a str>,
17    pub is_streaming: bool,
18    pub spinner_frame: usize,
19}
20
21impl<'a> StatusBar<'a> {
22    pub fn new(model: &'a str, mode: &'a str, cost: f64, git_branch: Option<&'a str>, is_streaming: bool, spinner_frame: usize) -> Self {
23        Self { model, mode, cost, git_branch, is_streaming, spinner_frame }
24    }
25}
26
27impl<'a> Widget for StatusBar<'a> {
28    fn render(self, area: Rect, buf: &mut Buffer) {
29        for x in area.x..area.x + area.width {
30            buf[(x, area.y)].set_style(Style::default().bg(theme::SURFACE()));
31        }
32
33        let sep = Span::styled("  ·  ", Style::default().fg(theme::HL_HIGH()).bg(theme::SURFACE()));
34
35        let mode_span = if self.is_streaming {
36            let ch = FRAMES[self.spinner_frame % FRAMES.len()];
37            Span::styled(format!("{ch} generating"), Style::default().fg(theme::IRIS()).bg(theme::SURFACE()).add_modifier(Modifier::ITALIC))
38        } else {
39            let (icon, color) = match self.mode {
40                "Auto-accept" => ("⚡ ", theme::GOLD()),
41                "Plan"        => ("◆ ", theme::IRIS()),
42                "Bypass"      => ("⚠ ", theme::LOVE()),
43                _             => ("● ", theme::FOAM()),
44            };
45            Span::styled(format!("{icon}{}", self.mode), Style::default().fg(color).bg(theme::SURFACE()))
46        };
47
48        let mut spans = vec![
49            Span::styled(" ", Style::default().bg(theme::SURFACE())),
50            Span::styled(self.model, Style::default().fg(theme::FOAM()).bg(theme::SURFACE()).add_modifier(Modifier::BOLD)),
51            sep.clone(),
52            mode_span,
53            sep.clone(),
54            Span::styled(format!("${:.4}", self.cost), Style::default().fg(theme::IRIS()).bg(theme::SURFACE())),
55        ];
56
57        if let Some(branch) = self.git_branch {
58            spans.push(sep);
59            spans.push(Span::styled(
60                format!("\u{E0A0} {branch}"),
61                Style::default().fg(theme::PINE()).bg(theme::SURFACE()),
62            ));
63        }
64
65        Paragraph::new(Line::from(spans)).render(area, buf);
66    }
67}