Add spinner animation to TUI status indicator (#1917)
## Summary - add a pulsing dot loader before the shimmering `Working` label in the status indicator widget and include a small test asserting the spinner character is rendered - also fix a small bug in the ran command header by adding a space between the ⚡ and `Ran command` https://github.com/user-attachments/assets/6768c9d2-e094-49cb-ad51-44bcac10aa6f ## Testing - `just fmt` - `just fix` *(failed: E0658 `let` expressions in core/src/client.rs)* - `cargo test --all-features` *(failed: E0658 `let` expressions in core/src/client.rs)* ------ https://chatgpt.com/codex/tasks/task_i_68941bffdb948322b0f4190bc9dbe7f6 --------- Co-authored-by: aibrahim-oai <aibrahim@openai.com>
This commit is contained in:
@@ -262,7 +262,7 @@ impl HistoryCell {
|
||||
let mut lines: Vec<Line<'static>> = Vec::new();
|
||||
let command_escaped = strip_bash_lc_and_escape(&command);
|
||||
lines.push(Line::from(vec![
|
||||
"⚡Ran command ".magenta(),
|
||||
"⚡ Ran command ".magenta(),
|
||||
command_escaped.into(),
|
||||
]));
|
||||
|
||||
@@ -556,7 +556,7 @@ impl HistoryCell {
|
||||
let mut header: Vec<Span> = Vec::new();
|
||||
header.push(Span::raw("📋"));
|
||||
header.push(Span::styled(
|
||||
"Updated",
|
||||
" Updated",
|
||||
Style::default().add_modifier(Modifier::BOLD).magenta(),
|
||||
));
|
||||
header.push(Span::raw(" to do list ["));
|
||||
|
||||
@@ -213,9 +213,20 @@ impl WidgetRef for StatusIndicatorWidget {
|
||||
// Plain rendering: no borders or padding so the live cell is visually indistinguishable from terminal scrollback.
|
||||
let inner_width = area.width as usize;
|
||||
|
||||
// Compose a single status line like: "▌ Working (Xs • Ctrl c to interrupt) <logs>"
|
||||
let mut spans: Vec<Span<'static>> = Vec::new();
|
||||
spans.push(Span::styled("▌ ", Style::default().fg(Color::Cyan)));
|
||||
|
||||
// Simple dim spinner to the left of the header.
|
||||
let spinner_frames = ['·', '•', '●', '•'];
|
||||
const SPINNER_SLOWDOWN: usize = 2;
|
||||
let spinner_ch = spinner_frames[(idx / SPINNER_SLOWDOWN) % spinner_frames.len()];
|
||||
spans.push(Span::styled(
|
||||
spinner_ch.to_string(),
|
||||
Style::default().fg(Color::DarkGray),
|
||||
));
|
||||
spans.push(Span::raw(" "));
|
||||
|
||||
// Space after header
|
||||
// Animated header after the left bar
|
||||
spans.extend(animated_spans);
|
||||
// Space between header and bracket block
|
||||
@@ -324,4 +335,23 @@ mod tests {
|
||||
}
|
||||
assert!(row.contains("Working"), "expected Working header: {row:?}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn spinner_is_rendered() {
|
||||
let (tx_raw, _rx) = channel::<AppEvent>();
|
||||
let tx = AppEventSender::new(tx_raw);
|
||||
let mut w = StatusIndicatorWidget::new(tx);
|
||||
w.restart_with_text("Hello".to_string());
|
||||
std::thread::sleep(std::time::Duration::from_millis(120));
|
||||
|
||||
let area = ratatui::layout::Rect::new(0, 0, 30, 1);
|
||||
let mut buf = ratatui::buffer::Buffer::empty(area);
|
||||
w.render_ref(area, &mut buf);
|
||||
|
||||
let ch = buf[(2, 0)].symbol().chars().next().unwrap_or(' ');
|
||||
assert!(
|
||||
matches!(ch, '·' | '•' | '●'),
|
||||
"expected spinner char at col 2: {ch:?}"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user