diff options
| author | Can Celik <ogulcancelik@gmail.com> | 2026-08-04 17:26:30 +0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-08-04 17:26:30 +0300 |
| commit | cc9fa47540d8525f24fe46a10f759ca40090a6e0 (patch) | |
| tree | ef6979a7d5168952dc2de8d7a68e42b3ad69c45b /src/app/input | |
| parent | 4473e391962c68d59bd980fa98a44f3397d9931d (diff) | |
feat(ui): add distinct status indicators (#2282)
refs #2260
Diffstat (limited to 'src/app/input')
| -rw-r--r-- | src/app/input/mod.rs | 3 | ||||
| -rw-r--r-- | src/app/input/settings.rs | 83 |
2 files changed, 79 insertions, 7 deletions
diff --git a/src/app/input/mod.rs b/src/app/input/mod.rs index 7eca40b6..f77821c9 100644 --- a/src/app/input/mod.rs +++ b/src/app/input/mod.rs @@ -399,6 +399,9 @@ impl App { } MouseAction::Settings(action) => match action { SettingsAction::SaveTheme(name) => self.save_theme(&name), + SettingsAction::SaveStatusIndicators(style) => { + self.save_status_indicators(style) + } SettingsAction::SaveSound(enabled) => self.save_sound(enabled), SettingsAction::SaveToastDelivery(delivery) => { self.save_toast_delivery(delivery) diff --git a/src/app/input/settings.rs b/src/app/input/settings.rs index 326d841b..fb1a7d75 100644 --- a/src/app/input/settings.rs +++ b/src/app/input/settings.rs @@ -6,7 +6,7 @@ use crate::{ state::{AppState, SettingsSection, THEME_NAMES}, App, Mode, }, - config::ToastDelivery, + config::{StatusIndicatorStyle, ToastDelivery}, }; #[derive(Debug, Clone, PartialEq, Eq)] @@ -14,6 +14,7 @@ use crate::{ #[allow(clippy::enum_variant_names)] pub(super) enum SettingsAction { SaveTheme(String), + SaveStatusIndicators(StatusIndicatorStyle), SaveSound(bool), SaveToastDelivery(ToastDelivery), SaveAgentBorderLabels(bool), @@ -26,6 +27,7 @@ impl App { if let Some(action) = update_settings_state(&mut self.state, key) { match action { SettingsAction::SaveTheme(name) => self.save_theme(&name), + SettingsAction::SaveStatusIndicators(style) => self.save_status_indicators(style), SettingsAction::SaveSound(enabled) => self.save_sound(enabled), SettingsAction::SaveToastDelivery(delivery) => self.save_toast_delivery(delivery), SettingsAction::SaveAgentBorderLabels(enabled) => { @@ -56,6 +58,21 @@ fn current_theme_index(theme_name: &str) -> usize { .unwrap_or(0) } +fn status_indicator_index(style: StatusIndicatorStyle) -> usize { + match style { + StatusIndicatorStyle::Dots => 0, + StatusIndicatorStyle::Symbols => 1, + } +} + +fn status_indicator_for_index(idx: usize) -> StatusIndicatorStyle { + if idx == 0 { + StatusIndicatorStyle::Dots + } else { + StatusIndicatorStyle::Symbols + } +} + fn toast_delivery_index(delivery: ToastDelivery) -> usize { match delivery { ToastDelivery::Off => 0, @@ -145,8 +162,8 @@ pub(super) fn update_settings_state(state: &mut AppState, key: KeyEvent) -> Opti } } KeyCode::Tab | KeyCode::Right | KeyCode::Char('l') => { - state.settings.section = SettingsSection::Sound; - state.settings.list.selected = usize::from(!state.sound_enabled()); + state.settings.section = SettingsSection::Indicators; + state.settings.list.selected = status_indicator_index(state.status_indicators); } KeyCode::BackTab | KeyCode::Left | KeyCode::Char('h') => { state.settings.section = SettingsSection::Integrations; @@ -158,6 +175,30 @@ pub(super) fn update_settings_state(state: &mut AppState, key: KeyEvent) -> Opti _ => {} }, }, + SettingsSection::Indicators => match key.code { + KeyCode::Up | KeyCode::Char('k') | KeyCode::Down | KeyCode::Char('j') => { + state.settings.list.selected = 1 - state.settings.list.selected.min(1); + } + KeyCode::Enter | KeyCode::Char(' ') => { + let style = status_indicator_for_index(state.settings.list.selected); + return Some(SettingsAction::SaveStatusIndicators(style)); + } + KeyCode::BackTab | KeyCode::Left | KeyCode::Char('h') => { + state.settings.section = SettingsSection::Theme; + state.settings.list.selected = current_theme_index(&state.theme_name); + } + KeyCode::Tab | KeyCode::Right | KeyCode::Char('l') => { + state.settings.section = SettingsSection::Sound; + state.settings.list.selected = usize::from(!state.sound_enabled()); + } + _ => { + if let Some(super::modal::ModalAction::Close) = + super::modal::modal_action_from_key(&key, super::modal::SETTINGS_ACTIONS) + { + cancel_settings(state); + } + } + }, SettingsSection::Sound => match key.code { KeyCode::Up | KeyCode::Char('k') | KeyCode::Down | KeyCode::Char('j') => { state.settings.list.selected = 1 - state.settings.list.selected.min(1); @@ -171,8 +212,8 @@ pub(super) fn update_settings_state(state: &mut AppState, key: KeyEvent) -> Opti state.settings.list.selected = toast_delivery_index(state.toast_delivery()); } KeyCode::BackTab | KeyCode::Left | KeyCode::Char('h') => { - state.settings.section = SettingsSection::Theme; - state.settings.list.selected = current_theme_index(&state.theme_name); + state.settings.section = SettingsSection::Indicators; + state.settings.list.selected = status_indicator_index(state.status_indicators); } _ => { if let Some(super::modal::ModalAction::Close) = @@ -263,6 +304,7 @@ pub(crate) fn open_settings_at(state: &mut AppState, section: SettingsSection) { state.settings.section = section; state.settings.list.selected = match section { SettingsSection::Theme => current_theme_index(&state.theme_name), + SettingsSection::Indicators => status_indicator_index(state.status_indicators), SettingsSection::Sound => usize::from(!state.sound_enabled()), SettingsSection::Toast => toast_delivery_index(state.toast_delivery()), SettingsSection::PaneLabels => usize::from(!state.agent_border_labels_enabled()), @@ -336,7 +378,7 @@ impl AppState { let idx = scroll + (row - area.y) as usize; (idx < THEME_NAMES.len()).then_some(idx) } - SettingsSection::Sound => { + SettingsSection::Indicators | SettingsSection::Sound => { let list_y = area.y + 3; if row >= list_y && row < list_y + 2 { Some((row - list_y) as usize) @@ -371,6 +413,9 @@ impl AppState { self.settings.section = section; self.settings.list.select(match section { SettingsSection::Theme => current_theme_index(&self.theme_name), + SettingsSection::Indicators => { + status_indicator_index(self.status_indicators) + } SettingsSection::Sound => usize::from(!self.sound_enabled()), SettingsSection::Toast => toast_delivery_index(self.toast_delivery()), SettingsSection::PaneLabels => { @@ -387,6 +432,9 @@ impl AppState { preview_selected_theme(self); None } + SettingsSection::Indicators => Some(SettingsAction::SaveStatusIndicators( + status_indicator_for_index(idx), + )), SettingsSection::Sound => { let enabled = idx == 0; Some(SettingsAction::SaveSound(enabled)) @@ -454,7 +502,7 @@ mod tests { ); assert_eq!( state.settings.section, - crate::app::state::SettingsSection::Sound + crate::app::state::SettingsSection::Indicators ); update_settings_state( @@ -469,6 +517,27 @@ mod tests { } #[test] + fn settings_indicator_choice_returns_save_action() { + let mut state = state_with_workspaces(&["test"]); + open_settings_at(&mut state, SettingsSection::Indicators); + state.settings.list.selected = 1; + + let action = update_settings_state( + &mut state, + KeyEvent::new(KeyCode::Enter, KeyModifiers::empty()), + ); + + assert_eq!( + action, + Some(SettingsAction::SaveStatusIndicators( + StatusIndicatorStyle::Symbols + )) + ); + assert_eq!(state.status_indicators, StatusIndicatorStyle::Dots); + assert_eq!(state.mode, Mode::Settings); + } + + #[test] fn settings_sound_toggle_returns_save_action() { let mut state = state_with_workspaces(&["test"]); open_settings(&mut state); |
