diff options
| author | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-07-28 14:56:51 +0300 |
|---|---|---|
| committer | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-07-28 14:56:53 +0300 |
| commit | 81f355fadac7d0d45b077dfc28f9f679add6bbb6 (patch) | |
| tree | 8c734b443c28ee4de8c4058f5a0c25cafbd057bd /src/ui | |
| parent | 1491b7dd9c992ef0ad2b763f3e450befaf25c47f (diff) | |
perf: replace agent spinners with static status marks
Diffstat (limited to 'src/ui')
| -rw-r--r-- | src/ui/mobile.rs | 13 | ||||
| -rw-r--r-- | src/ui/navigator.rs | 11 | ||||
| -rw-r--r-- | src/ui/sidebar.rs | 10 | ||||
| -rw-r--r-- | src/ui/status.rs | 31 |
4 files changed, 27 insertions, 38 deletions
diff --git a/src/ui/mobile.rs b/src/ui/mobile.rs index 10b58af0..299a152b 100644 --- a/src/ui/mobile.rs +++ b/src/ui/mobile.rs @@ -11,7 +11,7 @@ use super::sidebar::{ next_entry_is_indented_workspace, workspace_list_entries_expanded, AgentPanelEntry, WorkspaceListEntry, }; -use super::status::{agent_icon, state_dot}; +use super::status::state_dot; use super::text::{display_width_u16, truncate_end}; use crate::app::state::{Palette, ToastKind, ToastNotification}; use crate::app::AppState; @@ -326,14 +326,7 @@ fn render_header_status( }; let (state, seen) = ws.aggregate_state(&app.terminals); - let (dot, dot_style) = if matches!(state, AgentState::Working) { - ( - super::spinner_frame(app.spinner_tick), - Style::default().fg(p.yellow), - ) - } else { - state_dot(state, seen, p) - }; + let (dot, dot_style) = state_dot(state, seen, p); let tab_label = mobile_tab_status(ws); let row1 = Rect::new(area.x, area.y, area.width, 1); let tab_w = display_width_u16(&tab_label) @@ -539,7 +532,7 @@ fn render_mobile_switcher_content( entry.ws_idx == ws_idx && entry.tab_idx == tab_idx && entry.pane_id == pane_id }); let bg = mobile_item_bg(false, active, p); - let (icon, icon_style) = agent_icon(entry.state, entry.seen, app.spinner_tick, p); + let (icon, icon_style) = state_dot(entry.state, entry.seen, p); let title = Line::from(vec![ Span::styled(" ", Style::default().bg(bg)), Span::styled(icon, icon_style.bg(bg)), diff --git a/src/ui/navigator.rs b/src/ui/navigator.rs index 28eb8530..9269394b 100644 --- a/src/ui/navigator.rs +++ b/src/ui/navigator.rs @@ -8,7 +8,7 @@ use ratatui::{ use super::{ scrollbar::{render_scrollbar, should_show_scrollbar}, - status::{agent_icon, state_label_color}, + status::{state_dot, state_label_color}, text::{display_width_u16, middle_elide, truncate_end}, widgets::{panel_contrast_fg, render_panel_shell}, }; @@ -66,7 +66,6 @@ fn render_search(app: &AppState, frame: &mut Frame, area: Rect) { &mut spans, crate::detect::AgentState::Blocked, true, - app.spinner_tick, "blocked", app, ), @@ -74,7 +73,6 @@ fn render_search(app: &AppState, frame: &mut Frame, area: Rect) { &mut spans, crate::detect::AgentState::Working, true, - app.spinner_tick, "working", app, ), @@ -82,7 +80,6 @@ fn render_search(app: &AppState, frame: &mut Frame, area: Rect) { &mut spans, crate::detect::AgentState::Idle, true, - app.spinner_tick, "idle", app, ), @@ -90,7 +87,6 @@ fn render_search(app: &AppState, frame: &mut Frame, area: Rect) { &mut spans, crate::detect::AgentState::Idle, false, - app.spinner_tick, "done", app, ), @@ -114,11 +110,10 @@ fn push_state_chip( spans: &mut Vec<Span<'static>>, state: crate::detect::AgentState, seen: bool, - tick: u32, label: &'static str, app: &AppState, ) { - let (icon, icon_style) = agent_icon(state, seen, tick, &app.palette); + let (icon, icon_style) = state_dot(state, seen, &app.palette); spans.push(Span::styled(icon, icon_style.add_modifier(Modifier::BOLD))); spans.push(Span::raw(" ")); spans.push(Span::styled( @@ -206,7 +201,7 @@ fn render_row( } else { Style::default().fg(p.subtext0).bg(p.panel_bg) }; - let (status_icon, status_style) = agent_icon(row.status, row.seen, app.spinner_tick, p); + let (status_icon, status_style) = state_dot(row.status, row.seen, p); let status_style = if selected { base_style.add_modifier(Modifier::BOLD) } else if context_only { diff --git a/src/ui/sidebar.rs b/src/ui/sidebar.rs index 09078c17..c7ba659a 100644 --- a/src/ui/sidebar.rs +++ b/src/ui/sidebar.rs @@ -10,7 +10,7 @@ use ratatui::{ use self::tokens::{ResolvedToken, ResolvedTokenKind, SpaceTokenContext}; use super::scrollbar::{render_scrollbar, should_show_scrollbar}; -use super::status::{agent_icon, state_dot, state_label, state_label_color}; +use super::status::{state_dot, state_label, state_label_color}; use super::text::{display_width, display_width_u16, truncate_end}; use crate::app::state::{AgentPanelSort, Palette}; use crate::app::{AppState, Mode}; @@ -850,7 +850,7 @@ pub(super) fn render_sidebar_collapsed(app: &AppState, frame: &mut Frame, area: } let position = detail_idx + 1; let position_style = Style::default().fg(p.overlay0); - let (icon, icon_style) = agent_icon(detail.state, detail.seen, app.spinner_tick, p); + let (icon, icon_style) = state_dot(detail.state, detail.seen, p); frame.render_widget( Paragraph::new(Line::from(vec![ Span::styled(format!("{position:<2}"), position_style), @@ -1496,7 +1496,7 @@ fn render_agent_detail( Style::default().fg(label_color).add_modifier(Modifier::DIM) }; let agent_style = Style::default().fg(p.overlay0).add_modifier(Modifier::DIM); - let state_icon = agent_icon(detail.state, detail.seen, app.spinner_tick, p); + let state_icon = state_dot(detail.state, detail.seen, p); for (row_index, resolved) in rows.iter().take(height as usize).enumerate() { let mut spans = vec![Span::raw(if row_index == 0 { " " } else { " " })]; @@ -2161,7 +2161,7 @@ rows = [[{ token = "git_status", fg = "#123456" }]] let buffer = terminal.backend().buffer(); assert_eq!(buffer[(detail_area.x, tenth_row)].symbol(), "1"); assert_eq!(buffer[(detail_area.x + 1, tenth_row)].symbol(), "0"); - assert_eq!(buffer[(detail_area.x + 2, tenth_row)].symbol(), "○"); + assert_eq!(buffer[(detail_area.x + 2, tenth_row)].symbol(), "·"); } #[test] @@ -2205,7 +2205,7 @@ rows = [[{ token = "git_status", fg = "#123456" }]] assert_eq!(buffer[(detail_area.x, detail_area.y)].symbol(), "1"); assert_eq!(buffer[(detail_area.x, detail_area.y + 1)].symbol(), "2"); assert_eq!(buffer[(detail_area.x, detail_area.y + 2)].symbol(), "3"); - assert_eq!(buffer[(detail_area.x + 2, detail_area.y)].symbol(), "◉"); + assert_eq!(buffer[(detail_area.x + 2, detail_area.y)].symbol(), "●"); assert_eq!( buffer[(detail_area.x + 2, detail_area.y)].style().fg, Some(app.palette.red) diff --git a/src/ui/status.rs b/src/ui/status.rs index ede38b85..a7399285 100644 --- a/src/ui/status.rs +++ b/src/ui/status.rs @@ -203,21 +203,6 @@ pub(super) fn state_dot(state: AgentState, seen: bool, p: &Palette) -> (&'static } } -pub(super) fn agent_icon( - state: AgentState, - seen: bool, - tick: u32, - p: &Palette, -) -> (&'static str, Style) { - match (state, seen) { - (AgentState::Blocked, _) => ("◉", Style::default().fg(p.red)), - (AgentState::Working, _) => (super::spinner_frame(tick), Style::default().fg(p.yellow)), - (AgentState::Idle, false) => ("●", Style::default().fg(p.teal)), - (AgentState::Idle, true) => ("✓", Style::default().fg(p.green)), - (AgentState::Unknown, _) => ("○", Style::default().fg(p.overlay0)), - } -} - pub(super) fn state_label(state: AgentState, seen: bool) -> &'static str { match (state, seen) { (AgentState::Blocked, _) => "blocked", @@ -260,6 +245,22 @@ mod tests { } #[test] + fn state_dots_use_aligned_static_workspace_marks() { + let palette = Palette::catppuccin(); + for (state, seen, symbol, color) in [ + (AgentState::Blocked, true, "●", palette.red), + (AgentState::Working, true, "●", palette.yellow), + (AgentState::Idle, false, "●", palette.teal), + (AgentState::Idle, true, "○", palette.green), + (AgentState::Unknown, true, "·", palette.overlay0), + ] { + let (actual_symbol, style) = state_dot(state, seen, &palette); + assert_eq!(actual_symbol, symbol); + assert_eq!(style.fg, Some(color)); + } + } + + #[test] fn toast_rect_uses_configured_corner() { let area = Rect::new(10, 20, 100, 40); let toast = toast(); |
