mermaid_cli/render/widgets/
status_line.rs1use ratatui::{
2 buffer::Buffer,
3 layout::Rect,
4 style::Style,
5 text::{Line, Span},
6 widgets::{Paragraph, Widget},
7};
8use std::collections::VecDeque;
9
10use super::GenerationStatus;
11use crate::render::theme::Theme;
12
13pub struct StatusLineWidget<'a> {
15 pub status: GenerationStatus,
16 pub elapsed_secs: u64,
17 pub tokens_received: usize,
18 pub tokens_estimated: bool,
20 pub theme: &'a Theme,
21 pub queued_messages: &'a VecDeque<String>,
23}
24
25impl<'a> Widget for StatusLineWidget<'a> {
26 fn render(self, area: Rect, buf: &mut Buffer) {
27 if area.height == 0 || area.width < 10 {
29 return;
30 }
31
32 if self.status == GenerationStatus::Idle {
34 return;
35 }
36
37 let status_text = self.status.display_text();
38
39 let info_color = self.theme.colors.info.to_color();
40
41 let (arrow, flow_direction) = match self.status {
43 GenerationStatus::Sending | GenerationStatus::Thinking => ("↑ ", "upstream"),
44 GenerationStatus::Streaming => ("↓ ", "downstream"),
45 GenerationStatus::Idle => ("", ""),
46 };
47
48 let spans = vec![
49 Span::styled(arrow, Style::new().fg(info_color)),
51 Span::styled(format!("{}... ", status_text), Style::new().fg(info_color)),
53 Span::styled(
56 format!(
57 "(esc to interrupt • {}s • {} {}{} tokens)",
58 self.elapsed_secs,
59 if flow_direction == "downstream" {
60 "↓"
61 } else {
62 "↑"
63 },
64 if self.tokens_estimated { "~" } else { "" },
65 self.tokens_received
66 ),
67 Style::new()
68 .fg(self.theme.colors.text_secondary.to_color())
69 .dim(),
70 ),
71 ];
72
73 let mut lines = vec![Line::from(spans)];
74
75 let max_len = area.width.saturating_sub(4) as usize;
77 for queued in self.queued_messages.iter() {
78 let display_msg = if queued.len() > max_len {
80 let end = queued.floor_char_boundary(max_len.saturating_sub(3));
81 format!("> {}...", &queued[..end])
82 } else {
83 format!("> {}", queued)
84 };
85
86 lines.push(Line::from(vec![Span::styled(
87 display_msg,
88 Style::new()
89 .fg(self.theme.colors.text_primary.to_color())
90 .bg(ratatui::style::Color::Rgb(60, 60, 80)), )]));
92 }
93
94 let paragraph = Paragraph::new(lines);
95
96 paragraph.render(area, buf);
97 }
98}