diff --git a/codex-rs/tui/src/history_cell.rs b/codex-rs/tui/src/history_cell.rs index d7a06fa5..b87525a0 100644 --- a/codex-rs/tui/src/history_cell.rs +++ b/codex-rs/tui/src/history_cell.rs @@ -262,7 +262,7 @@ impl HistoryCell { let mut lines: Vec> = 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 = 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 [")); diff --git a/codex-rs/tui/src/status_indicator_widget.rs b/codex-rs/tui/src/status_indicator_widget.rs index fca9a23b..dcb8a5fd 100644 --- a/codex-rs/tui/src/status_indicator_widget.rs +++ b/codex-rs/tui/src/status_indicator_widget.rs @@ -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) " let mut spans: Vec> = 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::(); + 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:?}" + ); + } }