shimmer on working (#1807)
change the animation on "working" to be a text shimmer https://github.com/user-attachments/assets/f64529eb-1c64-493a-8d97-0f68b964bdd0
This commit is contained in:
16
codex-rs/Cargo.lock
generated
16
codex-rs/Cargo.lock
generated
@@ -869,6 +869,7 @@ dependencies = [
|
|||||||
"shlex",
|
"shlex",
|
||||||
"strum 0.27.2",
|
"strum 0.27.2",
|
||||||
"strum_macros 0.27.2",
|
"strum_macros 0.27.2",
|
||||||
|
"supports-color",
|
||||||
"textwrap 0.16.2",
|
"textwrap 0.16.2",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tracing",
|
"tracing",
|
||||||
@@ -2337,6 +2338,12 @@ dependencies = [
|
|||||||
"windows-sys 0.59.0",
|
"windows-sys 0.59.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "is_ci"
|
||||||
|
version = "1.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7655c9839580ee829dfacba1d1278c2b7883e50a277ff7541299489d6bdfdc45"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "is_terminal_polyfill"
|
name = "is_terminal_polyfill"
|
||||||
version = "1.70.1"
|
version = "1.70.1"
|
||||||
@@ -4378,6 +4385,15 @@ version = "2.6.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
|
checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "supports-color"
|
||||||
|
version = "3.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c64fc7232dd8d2e4ac5ce4ef302b1d81e0b80d055b9d77c7c4f51f6aa4c867d6"
|
||||||
|
dependencies = [
|
||||||
|
"is_ci",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "1.0.109"
|
version = "1.0.109"
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ serde_json = { version = "1", features = ["preserve_order"] }
|
|||||||
shlex = "1.3.0"
|
shlex = "1.3.0"
|
||||||
strum = "0.27.2"
|
strum = "0.27.2"
|
||||||
strum_macros = "0.27.2"
|
strum_macros = "0.27.2"
|
||||||
|
supports-color = "3.0.2"
|
||||||
textwrap = "0.16.2"
|
textwrap = "0.16.2"
|
||||||
tokio = { version = "1", features = [
|
tokio = { version = "1", features = [
|
||||||
"io-std",
|
"io-std",
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ impl StatusIndicatorWidget {
|
|||||||
thread::spawn(move || {
|
thread::spawn(move || {
|
||||||
let mut counter = 0usize;
|
let mut counter = 0usize;
|
||||||
while running_clone.load(Ordering::Relaxed) {
|
while running_clone.load(Ordering::Relaxed) {
|
||||||
std::thread::sleep(Duration::from_millis(200));
|
std::thread::sleep(Duration::from_millis(100));
|
||||||
counter = counter.wrapping_add(1);
|
counter = counter.wrapping_add(1);
|
||||||
frame_idx_clone.store(counter, Ordering::Relaxed);
|
frame_idx_clone.store(counter, Ordering::Relaxed);
|
||||||
app_event_tx_clone.send(AppEvent::RequestRedraw);
|
app_event_tx_clone.send(AppEvent::RequestRedraw);
|
||||||
@@ -98,46 +98,51 @@ impl WidgetRef for StatusIndicatorWidget {
|
|||||||
.borders(Borders::LEFT)
|
.borders(Borders::LEFT)
|
||||||
.border_type(BorderType::QuadrantOutside)
|
.border_type(BorderType::QuadrantOutside)
|
||||||
.border_style(widget_style.dim());
|
.border_style(widget_style.dim());
|
||||||
// Animated 3‑dot pattern inside brackets. The *active* dot is bold
|
|
||||||
// white, the others are dim.
|
|
||||||
const DOT_COUNT: usize = 3;
|
|
||||||
let idx = self.frame_idx.load(std::sync::atomic::Ordering::Relaxed);
|
let idx = self.frame_idx.load(std::sync::atomic::Ordering::Relaxed);
|
||||||
let phase = idx % (DOT_COUNT * 2 - 2);
|
let header_text = "Working";
|
||||||
let active = if phase < DOT_COUNT {
|
let header_chars: Vec<char> = header_text.chars().collect();
|
||||||
phase
|
|
||||||
} else {
|
let padding = 4usize; // virtual padding around the word for smoother loop
|
||||||
(DOT_COUNT * 2 - 2) - phase
|
let period = header_chars.len() + padding * 2;
|
||||||
};
|
let pos = idx % period;
|
||||||
|
|
||||||
|
let has_true_color = supports_color::on_cached(supports_color::Stream::Stdout)
|
||||||
|
.map(|level| level.has_16m)
|
||||||
|
.unwrap_or(false);
|
||||||
|
|
||||||
|
// Width of the bright band (in characters).
|
||||||
|
let band_half_width = 2.0;
|
||||||
|
|
||||||
let mut header_spans: Vec<Span<'static>> = Vec::new();
|
let mut header_spans: Vec<Span<'static>> = Vec::new();
|
||||||
|
for (i, ch) in header_chars.iter().enumerate() {
|
||||||
|
let i_pos = i as isize + padding as isize;
|
||||||
|
let pos = pos as isize;
|
||||||
|
let dist = (i_pos - pos).abs() as f32;
|
||||||
|
|
||||||
header_spans.push(Span::styled(
|
let t = if dist <= band_half_width {
|
||||||
"Working ",
|
let x = std::f32::consts::PI * (dist / band_half_width);
|
||||||
Style::default()
|
0.5 * (1.0 + x.cos())
|
||||||
.fg(Color::White)
|
} else {
|
||||||
.add_modifier(Modifier::BOLD),
|
0.0
|
||||||
));
|
};
|
||||||
|
|
||||||
header_spans.push(Span::styled(
|
let brightness = 0.4 + 0.6 * t;
|
||||||
"[",
|
let level = (brightness * 255.0).clamp(0.0, 255.0) as u8;
|
||||||
|
let style = if has_true_color {
|
||||||
Style::default()
|
Style::default()
|
||||||
.fg(Color::White)
|
.fg(Color::Rgb(level, level, level))
|
||||||
.add_modifier(Modifier::BOLD),
|
|
||||||
));
|
|
||||||
|
|
||||||
for i in 0..DOT_COUNT {
|
|
||||||
let style = if i == active {
|
|
||||||
Style::default()
|
|
||||||
.fg(Color::White)
|
|
||||||
.add_modifier(Modifier::BOLD)
|
.add_modifier(Modifier::BOLD)
|
||||||
} else {
|
} else {
|
||||||
Style::default().dim()
|
// Bold makes dark gray and gray look the same, so don't use it
|
||||||
|
// when true color is not supported.
|
||||||
|
Style::default().fg(color_for_level(level))
|
||||||
};
|
};
|
||||||
header_spans.push(Span::styled(".", style));
|
|
||||||
|
header_spans.push(Span::styled(ch.to_string(), style));
|
||||||
}
|
}
|
||||||
|
|
||||||
header_spans.push(Span::styled(
|
header_spans.push(Span::styled(
|
||||||
"] ",
|
" ",
|
||||||
Style::default()
|
Style::default()
|
||||||
.fg(Color::White)
|
.fg(Color::White)
|
||||||
.add_modifier(Modifier::BOLD),
|
.add_modifier(Modifier::BOLD),
|
||||||
@@ -189,3 +194,13 @@ impl WidgetRef for StatusIndicatorWidget {
|
|||||||
paragraph.render_ref(area, buf);
|
paragraph.render_ref(area, buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn color_for_level(level: u8) -> Color {
|
||||||
|
if level < 128 {
|
||||||
|
Color::DarkGray
|
||||||
|
} else if level < 192 {
|
||||||
|
Color::Gray
|
||||||
|
} else {
|
||||||
|
Color::White
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user