aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/app/input/mouse.rs10
-rw-r--r--src/app/input/sidebar.rs56
-rw-r--r--src/ui.rs7
-rw-r--r--src/ui/sidebar.rs54
4 files changed, 108 insertions, 19 deletions
diff --git a/src/app/input/mouse.rs b/src/app/input/mouse.rs
index cc03c8f6..b991828a 100644
--- a/src/app/input/mouse.rs
+++ b/src/app/input/mouse.rs
@@ -449,12 +449,12 @@ impl AppState {
}
if in_sidebar {
- if self.sidebar_collapsed {
- if self.on_collapsed_sidebar_toggle(mouse.column, mouse.row) {
- self.sidebar_collapsed = false;
- return None;
- }
+ if self.on_sidebar_toggle(mouse.column, mouse.row) {
+ self.sidebar_collapsed = !self.sidebar_collapsed;
+ return None;
+ }
+ if self.sidebar_collapsed {
if let Some(idx) = self.collapsed_workspace_at_row(mouse.row) {
self.switch_workspace(idx);
self.mode = Mode::Terminal;
diff --git a/src/app/input/sidebar.rs b/src/app/input/sidebar.rs
index 8ba12bc6..43093a82 100644
--- a/src/app/input/sidebar.rs
+++ b/src/app/input/sidebar.rs
@@ -238,17 +238,25 @@ impl AppState {
return false;
}
let sidebar = self.view.sidebar_rect;
+ let toggle = crate::ui::expanded_sidebar_toggle_rect(sidebar);
+ let on_toggle = toggle.width > 0
+ && col >= toggle.x
+ && col < toggle.x + toggle.width
+ && row >= toggle.y
+ && row < toggle.y + toggle.height;
sidebar.width > 0
+ && !on_toggle
&& col == sidebar.x + sidebar.width.saturating_sub(1)
&& row >= sidebar.y
&& row < sidebar.y + sidebar.height
}
- pub(super) fn on_collapsed_sidebar_toggle(&self, col: u16, row: u16) -> bool {
- if !self.sidebar_collapsed {
- return false;
- }
- let rect = crate::ui::collapsed_sidebar_toggle_rect(self.view.sidebar_rect);
+ pub(super) fn on_sidebar_toggle(&self, col: u16, row: u16) -> bool {
+ let rect = if self.sidebar_collapsed {
+ crate::ui::collapsed_sidebar_toggle_rect(self.view.sidebar_rect)
+ } else {
+ crate::ui::expanded_sidebar_toggle_rect(self.view.sidebar_rect)
+ };
rect.width > 0
&& col >= rect.x
&& col < rect.x + rect.width
@@ -970,6 +978,24 @@ mod tests {
}
#[test]
+ fn clicking_expanded_sidebar_toggle_collapses_sidebar() {
+ let mut app = app_for_mouse_test();
+ app.state.sidebar_collapsed = false;
+ app.state.view.sidebar_rect = Rect::new(0, 0, 26, 20);
+ app.state.view.terminal_area = Rect::new(26, 0, 80, 20);
+
+ let toggle = crate::ui::expanded_sidebar_toggle_rect(app.state.view.sidebar_rect);
+ app.handle_mouse(mouse(
+ MouseEventKind::Down(MouseButton::Left),
+ toggle.x,
+ toggle.y,
+ ));
+
+ assert!(app.state.sidebar_collapsed);
+ assert!(app.state.drag.is_none());
+ }
+
+ #[test]
fn clicking_workspace_switches_on_mouse_up() {
let mut app = app_for_mouse_test();
app.state.workspaces = vec![Workspace::test_new("a"), Workspace::test_new("b")];
@@ -1455,6 +1481,26 @@ mod tests {
}
#[test]
+ fn dragging_sidebar_bottom_divider_still_sets_manual_width() {
+ let mut app = app_for_mouse_test();
+ let divider_col = app.state.view.sidebar_rect.x + app.state.view.sidebar_rect.width - 1;
+ let bottom_row = app.state.view.sidebar_rect.y + app.state.view.sidebar_rect.height - 1;
+
+ app.handle_mouse(mouse(
+ MouseEventKind::Down(MouseButton::Left),
+ divider_col,
+ bottom_row,
+ ));
+ app.handle_mouse(mouse(
+ MouseEventKind::Drag(MouseButton::Left),
+ divider_col + 5,
+ bottom_row,
+ ));
+
+ assert_eq!(app.state.sidebar_width, 31);
+ }
+
+ #[test]
fn dragging_past_max_clamps_to_configured_max() {
let mut app = app_for_mouse_test();
app.state.sidebar_max_width = 30;
diff --git a/src/ui.rs b/src/ui.rs
index eb958d02..f6fc54d4 100644
--- a/src/ui.rs
+++ b/src/ui.rs
@@ -68,9 +68,10 @@ pub(crate) use self::{
agent_panel_body_rect, agent_panel_entries, agent_panel_scroll_metrics,
agent_panel_scrollbar_rect, agent_panel_toggle_rect, collapsed_sidebar_sections,
collapsed_sidebar_toggle_rect, compute_workspace_card_areas, expanded_sidebar_sections,
- normalized_workspace_scroll, sidebar_section_divider_rect, workspace_drop_indicator_row,
- workspace_list_entries, workspace_list_rect, workspace_list_scroll_metrics,
- workspace_list_scrollbar_rect, workspace_parent_group_state, WorkspaceListEntry,
+ expanded_sidebar_toggle_rect, normalized_workspace_scroll, sidebar_section_divider_rect,
+ workspace_drop_indicator_row, workspace_list_entries, workspace_list_rect,
+ workspace_list_scroll_metrics, workspace_list_scrollbar_rect, workspace_parent_group_state,
+ WorkspaceListEntry,
},
};
pub(crate) use self::{
diff --git a/src/ui/sidebar.rs b/src/ui/sidebar.rs
index 692e0236..7d1227df 100644
--- a/src/ui/sidebar.rs
+++ b/src/ui/sidebar.rs
@@ -1179,6 +1179,18 @@ pub(crate) fn collapsed_sidebar_toggle_rect(area: Rect) -> Rect {
Rect::new(x, bottom_y, 1, 1)
}
+pub(crate) fn expanded_sidebar_toggle_rect(area: Rect) -> Rect {
+ if area.width <= 1 || area.height == 0 {
+ return Rect::default();
+ }
+ Rect::new(
+ area.x + area.width.saturating_sub(2),
+ area.y + area.height.saturating_sub(1),
+ 1,
+ 1,
+ )
+}
+
fn render_sidebar_toggle(
app: &AppState,
frame: &mut Frame,
@@ -1186,25 +1198,55 @@ fn render_sidebar_toggle(
collapsed: bool,
p: &Palette,
) {
- if !collapsed {
- return;
- }
- let toggle_area = collapsed_sidebar_toggle_rect(area);
+ let toggle_area = if collapsed {
+ collapsed_sidebar_toggle_rect(area)
+ } else {
+ expanded_sidebar_toggle_rect(area)
+ };
if toggle_area == Rect::default() {
return;
}
- let icon_style = if app.global_menu_attention_badge_visible() {
+ let icon = if collapsed { "»" } else { "«" };
+ let icon_style = if collapsed && app.global_menu_attention_badge_visible() {
Style::default().fg(p.accent).add_modifier(Modifier::BOLD)
} else {
Style::default().fg(p.overlay0)
};
- frame.render_widget(Paragraph::new(Span::styled("»", icon_style)), toggle_area);
+ frame.render_widget(Paragraph::new(Span::styled(icon, icon_style)), toggle_area);
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{detect::Agent, workspace::Workspace};
+ use ratatui::{backend::TestBackend, Terminal};
+
+ #[test]
+ fn render_sidebar_toggle_draws_expanded_collapse_icon() {
+ let app = crate::app::state::AppState::test_new();
+ let area = Rect::new(0, 0, 26, 20);
+ let mut terminal =
+ Terminal::new(TestBackend::new(26, 20)).expect("test terminal should initialize");
+
+ terminal
+ .draw(|frame| render_sidebar_toggle(&app, frame, area, false, &app.palette))
+ .expect("sidebar toggle should render");
+
+ let toggle = expanded_sidebar_toggle_rect(area);
+ assert_eq!(
+ terminal.backend().buffer()[(toggle.x, toggle.y)].symbol(),
+ "«"
+ );
+ }
+
+ #[test]
+ fn expanded_sidebar_toggle_sits_inside_sidebar_content() {
+ let area = Rect::new(0, 0, 26, 20);
+ let toggle = expanded_sidebar_toggle_rect(area);
+
+ assert_eq!(toggle.x, area.x + area.width - 2);
+ assert_eq!(toggle.y, area.y + area.height - 1);
+ }
#[test]
fn all_workspaces_agent_panel_entries_use_workspace_and_optional_tab_labels() {