diff options
Diffstat (limited to 'src/app/input/mouse.rs')
| -rw-r--r-- | src/app/input/mouse.rs | 98 |
1 files changed, 88 insertions, 10 deletions
diff --git a/src/app/input/mouse.rs b/src/app/input/mouse.rs index 71c0cfbd..7f9f9cde 100644 --- a/src/app/input/mouse.rs +++ b/src/app/input/mouse.rs @@ -18,8 +18,7 @@ use crate::{ use super::WheelRouting; use super::{ modal::{ - apply_context_menu_action, apply_global_menu_action, apply_rename_action, - confirm_close_accept, confirm_close_cancel, global_menu_actions, leave_modal, + apply_global_menu_action, confirm_close_cancel, global_menu_actions, leave_modal, modal_action_from_buttons, open_global_menu, open_new_tab_dialog, ModalAction, }, settings::SettingsAction, @@ -52,6 +51,12 @@ pub(super) enum MouseAction { path: Vec<bool>, ratio: f32, }, + RenameModal(ModalAction), + ConfirmCloseAccept, + ContextMenu { + menu: ContextMenuState, + idx: usize, + }, } enum MobileMouseResult { @@ -234,7 +239,9 @@ impl AppState { (cancel, ModalAction::Cancel), ], ) { - Some(ModalAction::Confirm) => confirm_close_accept(self), + Some(ModalAction::Confirm) => { + return Some(MouseAction::ConfirmCloseAccept); + } Some(ModalAction::Cancel) | None => confirm_close_cancel(self), _ => {} } @@ -396,15 +403,14 @@ impl AppState { ) }) .unwrap_or(ModalAction::Cancel); - apply_rename_action(self, action); - return None; + return Some(MouseAction::RenameModal(action)); } if self.mode == Mode::ContextMenu { let item_idx = self.context_menu_item_at(mouse.column, mouse.row); if let Some(menu) = self.context_menu.take() { if let Some(idx) = item_idx { - apply_context_menu_action(self, terminal_runtimes, menu, idx); + return Some(MouseAction::ContextMenu { menu, idx }); } else { leave_modal(self); } @@ -900,8 +906,26 @@ impl AppState { if self.on_tab_bar(mouse.column, mouse.row) => { match mouse.kind { - MouseEventKind::ScrollUp => self.previous_tab(), - MouseEventKind::ScrollDown => self.next_tab(), + MouseEventKind::ScrollUp => { + if let Some(ws) = self.active.and_then(|i| self.workspaces.get(i)) { + if !ws.tabs.is_empty() { + let prev = if ws.active_tab == 0 { + ws.tabs.len() - 1 + } else { + ws.active_tab - 1 + }; + return Some(MouseAction::FocusTab { tab_idx: prev }); + } + } + } + MouseEventKind::ScrollDown => { + if let Some(ws) = self.active.and_then(|i| self.workspaces.get(i)) { + if !ws.tabs.is_empty() { + let next = (ws.active_tab + 1) % ws.tabs.len(); + return Some(MouseAction::FocusTab { tab_idx: next }); + } + } + } _ => {} } } @@ -1814,10 +1838,10 @@ mod tests { use ratatui::layout::{Direction, Rect}; use super::super::{ - app_for_mouse_test, capture_snapshot, handle_context_menu_key, mouse, numbered_lines_bytes, - root_layout_ratio, + app_for_mouse_test, capture_snapshot, mouse, numbered_lines_bytes, root_layout_ratio, }; use super::*; + use crate::app::input::modal::handle_context_menu_key; use crate::{ app::state::{ContextMenuKind, ContextMenuState, MenuListState, Mode, ViewLayout}, detect::{Agent, AgentState}, @@ -2450,6 +2474,31 @@ mod tests { } #[test] + fn clicking_rename_save_submits_workspace_rename_through_api_path() { + let mut app = app_for_mouse_test(); + app.state.workspaces = vec![Workspace::test_new("old")]; + app.state.active = Some(0); + app.state.selected = 0; + app.state.mode = Mode::RenameWorkspace; + app.state.name_input = "new".into(); + + crate::ui::compute_view(&mut app.state, Rect::new(0, 0, 106, 24)); + let inner = app.state.rename_modal_inner().unwrap(); + let (save, _, _) = crate::ui::rename_button_rects(inner); + + app.handle_mouse(mouse( + MouseEventKind::Down(MouseButton::Left), + save.x, + save.y, + )); + + assert_eq!(app.state.workspaces[0].custom_name.as_deref(), Some("new")); + assert!(app.event_hub.events_after(0).iter().any(|(_, event)| { + matches!(event.event, crate::api::schema::EventKind::WorkspaceRenamed) + })); + } + + #[test] fn clicking_open_worktree_row_selects_and_requests_open() { let mut app = app_for_mouse_test(); app.state.mode = Mode::OpenExistingWorktree; @@ -2615,6 +2664,35 @@ mod tests { assert_eq!(app.state.workspaces[0].display_name(), "a"); } + #[test] + fn clicking_context_menu_close_routes_through_api_path() { + let mut app = app_for_mouse_test(); + app.state.workspaces = vec![Workspace::test_new("a"), Workspace::test_new("b")]; + app.state.active = Some(0); + app.state.selected = 0; + app.state.confirm_close = false; + app.state.context_menu = Some(ContextMenuState { + kind: ContextMenuKind::Workspace { ws_idx: 1 }, + x: 2, + y: 2, + list: MenuListState::new(1), + }); + app.state.mode = Mode::ContextMenu; + + let menu = app.state.context_menu_rect().unwrap(); + app.handle_mouse(mouse( + MouseEventKind::Down(MouseButton::Left), + menu.x + 2, + menu.y + 2, + )); + + assert_eq!(app.state.workspaces.len(), 1); + assert_eq!(app.state.workspaces[0].display_name(), "a"); + assert!(app.event_hub.events_after(0).iter().any(|(_, event)| { + matches!(event.event, crate::api::schema::EventKind::WorkspaceClosed) + })); + } + #[cfg(unix)] #[tokio::test] async fn keyboard_context_menu_split_keeps_new_runtime() { |
