diff options
| author | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-04-06 16:13:12 +0300 |
|---|---|---|
| committer | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-04-06 16:13:12 +0300 |
| commit | c1e100be8fa15bc51f3c2e0b1edb38aa95a7cccd (patch) | |
| tree | b6d1a306e52da01a2bd03abb0e0348658674fd74 /src/app/actions.rs | |
| parent | fdea0bbbf606fcd8cfec1613a3aaf610bfb9b3cf (diff) | |
fix(ui): make sidebar spaces list scrollable
Diffstat (limited to 'src/app/actions.rs')
| -rw-r--r-- | src/app/actions.rs | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/src/app/actions.rs b/src/app/actions.rs index 340d3089..ac9b9243 100644 --- a/src/app/actions.rs +++ b/src/app/actions.rs @@ -106,12 +106,43 @@ impl AppState { if idx < self.workspaces.len() { self.active = Some(idx); self.selected = idx; + self.ensure_workspace_visible(idx); if let Some(ws) = self.workspaces.get_mut(idx) { ws.switch_tab(ws.active_tab); } } } + pub(crate) fn ensure_workspace_visible(&mut self, idx: usize) { + if self.sidebar_collapsed || idx >= self.workspaces.len() { + return; + } + + let mut cards = crate::ui::compute_workspace_card_areas(self, self.view.sidebar_rect); + if cards.is_empty() { + self.workspace_scroll = idx; + return; + } + + let first_idx = cards.first().map(|card| card.ws_idx).unwrap_or(0); + if idx < first_idx { + self.workspace_scroll = idx; + return; + } + + while cards.last().map(|card| card.ws_idx).unwrap_or(idx) < idx { + let previous_scroll = self.workspace_scroll; + self.workspace_scroll = self.workspace_scroll.saturating_add(1); + if self.workspace_scroll == previous_scroll { + break; + } + cards = crate::ui::compute_workspace_card_areas(self, self.view.sidebar_rect); + if cards.is_empty() { + break; + } + } + } + pub fn switch_tab(&mut self, idx: usize) { if let Some(ws) = self.active.and_then(|i| self.workspaces.get_mut(i)) { ws.switch_tab(idx); @@ -162,6 +193,7 @@ impl AppState { self.selected = selected_id .and_then(|id| self.workspaces.iter().position(|ws| ws.id == id)) .unwrap_or(0); + self.ensure_workspace_visible(self.selected); } pub fn next_tab(&mut self) { @@ -196,11 +228,16 @@ impl AppState { if self.workspaces.is_empty() { self.active = None; self.selected = 0; + self.workspace_scroll = 0; } else { if self.selected >= self.workspaces.len() { self.selected = self.workspaces.len() - 1; } self.active = Some(self.selected); + self.workspace_scroll = self + .workspace_scroll + .min(self.workspaces.len().saturating_sub(1)); + self.ensure_workspace_visible(self.selected); } } } @@ -543,6 +580,21 @@ mod tests { } #[test] + fn switch_workspace_keeps_selected_visible_in_scrolled_sidebar() { + let mut state = app_with_workspaces(&["a", "b", "c", "d", "e", "f", "g", "h"]); + crate::ui::compute_view(&mut state, ratatui::layout::Rect::new(0, 0, 26, 14)); + + state.switch_workspace(7); + crate::ui::compute_view(&mut state, ratatui::layout::Rect::new(0, 0, 26, 14)); + + assert!(state + .view + .workspace_card_areas + .iter() + .any(|card| card.ws_idx == 7)); + } + + #[test] fn switch_workspace_marks_panes_seen() { let mut state = app_with_workspaces(&["a", "b"]); // Mark a pane in workspace 1 as unseen |
