diff options
| author | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-06-29 18:09:25 +0300 |
|---|---|---|
| committer | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-06-29 18:09:25 +0300 |
| commit | 1a4e94e57e181379e2ed42d63a49fbc56ed1dba4 (patch) | |
| tree | 0319544374f1149a405259070b90df9d62854789 /src/app/api/panes.rs | |
| parent | a937f7e85bbf8780c6030c57f48dab2168bca932 (diff) | |
refactor: route tui mutations through runtime authority
Diffstat (limited to 'src/app/api/panes.rs')
| -rw-r--r-- | src/app/api/panes.rs | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/src/app/api/panes.rs b/src/app/api/panes.rs index 983db238..b2f5030a 100644 --- a/src/app/api/panes.rs +++ b/src/app/api/panes.rs @@ -161,6 +161,23 @@ impl App { encode_success(id, ResponseResult::PaneInfo { pane }) } + pub(super) fn handle_pane_focus(&mut self, id: String, target: PaneTarget) -> String { + let Some((ws_idx, pane_id)) = self.parse_pane_id(&target.pane_id) else { + return pane_not_found(id, &target.pane_id); + }; + let Some(_tab_idx) = self.state.workspaces[ws_idx].find_tab_index_for_pane(pane_id) else { + return pane_not_found(id, &target.pane_id); + }; + + self.state.focus_pane_in_workspace(ws_idx, pane_id); + self.state.mode = Mode::Terminal; + + let Some(pane) = self.pane_info(ws_idx, pane_id) else { + return pane_not_found(id, &target.pane_id); + }; + encode_success(id, ResponseResult::PaneInfo { pane }) + } + pub(super) fn handle_pane_layout(&mut self, id: String, params: PaneLayoutParams) -> String { let Some((ws_idx, pane_id)) = self.resolve_optional_pane(params.pane_id.as_deref()) else { return encode_error(id, "pane_not_found", "pane not found"); @@ -3204,6 +3221,51 @@ mod tests { } #[test] + fn api_pane_focus_focuses_direct_target_across_tabs_and_workspaces() { + let mut app = app_with_linked_worktree(); + app.state.workspaces.push(Workspace::test_new("other")); + let target_tab_idx = app.state.workspaces[1].test_add_tab(Some("target")); + app.state.workspaces[1].switch_tab(target_tab_idx); + let target_pane = app.state.workspaces[1].tabs[target_tab_idx].root_pane; + app.state.ensure_test_terminals(); + let target_public = app.public_pane_id(1, target_pane).unwrap(); + app.state.switch_workspace(0); + assert_eq!(app.state.active, Some(0)); + + let response = app.handle_pane_focus( + "req".into(), + crate::api::schema::PaneTarget { + pane_id: target_public.clone(), + }, + ); + + let success: SuccessResponse = serde_json::from_str(&response).unwrap(); + let ResponseResult::PaneInfo { pane } = success.result else { + panic!("expected pane info response"); + }; + assert_eq!(pane.pane_id, target_public); + assert_eq!(app.state.active, Some(1)); + assert_eq!(app.state.workspaces[1].active_tab, target_tab_idx); + assert_eq!(app.state.workspaces[1].focused_pane_id(), Some(target_pane)); + assert_eq!(app.state.mode, Mode::Terminal); + } + + #[test] + fn api_pane_focus_rejects_invalid_pane_id() { + let mut app = app_with_linked_worktree(); + + let response = app.handle_pane_focus( + "req".into(), + crate::api::schema::PaneTarget { + pane_id: "pane_missing".into(), + }, + ); + + let error: ErrorResponse = serde_json::from_str(&response).unwrap(); + assert_eq!(error.error.code, "pane_not_found"); + } + + #[test] fn api_pane_focus_direction_no_neighbor_is_noop() { let mut app = app_with_linked_worktree(); let root = app.state.workspaces[0].tabs[0].root_pane; |
