tui: breathing spinner on true-color terms (#4853)
uses the same logic as shimmer_spans to render the `•` spinner. on terminals without true-color support, fall back to the existing `•/◦` blinking logic. https://github.com/user-attachments/assets/19db76f2-8fa2-440d-9fde-7bed67f4c4dc
This commit is contained in:
@@ -8,6 +8,7 @@ use crate::history_cell::HistoryCell;
|
||||
use crate::render::highlight::highlight_bash_to_lines;
|
||||
use crate::render::line_utils::prefix_lines;
|
||||
use crate::render::line_utils::push_owned_lines;
|
||||
use crate::shimmer::shimmer_spans;
|
||||
use crate::wrapping::RtOptions;
|
||||
use crate::wrapping::word_wrap_line;
|
||||
use codex_ansi_escape::ansi_escape_line;
|
||||
@@ -116,10 +117,16 @@ pub(crate) fn output_lines(
|
||||
}
|
||||
|
||||
pub(crate) fn spinner(start_time: Option<Instant>) -> Span<'static> {
|
||||
let blink_on = start_time
|
||||
.map(|st| ((st.elapsed().as_millis() / 600) % 2) == 0)
|
||||
.unwrap_or(false);
|
||||
if blink_on { "•".into() } else { "◦".dim() }
|
||||
let elapsed = start_time.map(|st| st.elapsed()).unwrap_or_default();
|
||||
if supports_color::on_cached(supports_color::Stream::Stdout)
|
||||
.map(|level| level.has_16m)
|
||||
.unwrap_or(false)
|
||||
{
|
||||
shimmer_spans("•")[0].clone()
|
||||
} else {
|
||||
let blink_on = (elapsed.as_millis() / 600).is_multiple_of(2);
|
||||
if blink_on { "•".into() } else { "◦".dim() }
|
||||
}
|
||||
}
|
||||
|
||||
impl HistoryCell for ExecCell {
|
||||
|
||||
@@ -15,6 +15,7 @@ use ratatui::widgets::WidgetRef;
|
||||
|
||||
use crate::app_event::AppEvent;
|
||||
use crate::app_event_sender::AppEventSender;
|
||||
use crate::exec_cell::spinner;
|
||||
use crate::key_hint;
|
||||
use crate::shimmer::shimmer_spans;
|
||||
use crate::tui::FrameRequester;
|
||||
@@ -163,15 +164,11 @@ impl WidgetRef for StatusIndicatorWidget {
|
||||
let now = Instant::now();
|
||||
let elapsed_duration = self.elapsed_duration_at(now);
|
||||
let pretty_elapsed = fmt_elapsed_compact(elapsed_duration.as_secs());
|
||||
let blink_on = (elapsed_duration.as_millis() / 600).is_multiple_of(2);
|
||||
|
||||
// Plain rendering: no borders or padding so the live cell is visually indistinguishable from terminal scrollback.
|
||||
let mut spans = Vec::with_capacity(5);
|
||||
if blink_on {
|
||||
spans.push("• ".into());
|
||||
} else {
|
||||
spans.push("◦ ".dim());
|
||||
}
|
||||
spans.push(spinner(Some(self.last_resume_at)));
|
||||
spans.push(" ".into());
|
||||
spans.extend(shimmer_spans(&self.header));
|
||||
spans.extend(vec![
|
||||
" ".into(),
|
||||
|
||||
Reference in New Issue
Block a user