diff options
| author | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-04-10 15:00:32 +0300 |
|---|---|---|
| committer | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-04-10 15:00:34 +0300 |
| commit | 08eccb89d2c0717544902b6629b91b930f848461 (patch) | |
| tree | d6c6cc28167ec881a5e105a6ce8129cfed6978d9 /src/app | |
| parent | a763406db22dc81d5b2c141bf024e81df8b79fd7 (diff) | |
fix: preserve workspace when closing the last pane in a tab
Diffstat (limited to 'src/app')
| -rw-r--r-- | src/app/mod.rs | 75 |
1 files changed, 63 insertions, 12 deletions
diff --git a/src/app/mod.rs b/src/app/mod.rs index cefd0252..985d2322 100644 --- a/src/app/mod.rs +++ b/src/app/mod.rs @@ -1876,18 +1876,20 @@ impl App { .unwrap(); }; let workspace_id = self.state.workspaces[ws_idx].id.clone(); - let Some(ws) = self.state.workspaces.get_mut(ws_idx) else { - return serde_json::to_string(&ErrorResponse { - id: request.id, - error: ErrorBody { - code: "pane_not_found".into(), - message: format!("pane {} not found", target.pane_id), - }, - }) - .unwrap(); + let should_close_workspace = { + let Some(ws) = self.state.workspaces.get_mut(ws_idx) else { + return serde_json::to_string(&ErrorResponse { + id: request.id, + error: ErrorBody { + code: "pane_not_found".into(), + message: format!("pane {} not found", target.pane_id), + }, + }) + .unwrap(); + }; + ws.close_pane(pane_id) }; - let pane_count = ws.layout.pane_count(); - if pane_count <= 1 { + if should_close_workspace { self.state.selected = ws_idx; self.state.close_selected_workspace(); self.emit_event(crate::api::schema::EventEnvelope { @@ -1902,7 +1904,6 @@ impl App { data: crate::api::schema::EventData::WorkspaceClosed { workspace_id }, }); } else { - ws.close_pane(pane_id); self.schedule_session_save(); self.emit_event(crate::api::schema::EventEnvelope { event: crate::api::schema::EventKind::PaneClosed, @@ -2795,6 +2796,56 @@ mod tests { } #[test] + fn pane_close_request_closes_only_the_target_tab_when_other_tabs_exist() { + let mut app = test_app(); + let mut workspace = Workspace::test_new("api-pane-close"); + let second_tab = workspace.test_add_tab(Some("logs")); + workspace.switch_tab(second_tab); + app.state.workspaces = vec![workspace]; + app.state.active = Some(0); + app.state.selected = 0; + + let target_pane = app.state.workspaces[0].tabs[second_tab].root_pane; + let target_pane_id = app.pane_info(0, target_pane).unwrap().pane_id; + + let response = app.handle_api_request(crate::api::schema::Request { + id: "req_pane_close".into(), + method: crate::api::schema::Method::PaneClose(crate::api::schema::PaneTarget { + pane_id: target_pane_id, + }), + }); + let response: serde_json::Value = serde_json::from_str(&response).unwrap(); + + assert_eq!(response["result"]["type"], "ok"); + assert_eq!(app.state.workspaces.len(), 1); + assert_eq!(app.state.workspaces[0].tabs.len(), 1); + assert_eq!(app.state.workspaces[0].display_name(), "api-pane-close"); + } + + #[test] + fn pane_close_request_closes_workspace_when_it_removes_the_last_pane() { + let mut app = test_app(); + let workspace = Workspace::test_new("api-pane-close-last"); + app.state.workspaces = vec![workspace]; + app.state.active = Some(0); + app.state.selected = 0; + + let target_pane = app.state.workspaces[0].tabs[0].root_pane; + let target_pane_id = app.pane_info(0, target_pane).unwrap().pane_id; + + let response = app.handle_api_request(crate::api::schema::Request { + id: "req_pane_close_last".into(), + method: crate::api::schema::Method::PaneClose(crate::api::schema::PaneTarget { + pane_id: target_pane_id, + }), + }); + let response: serde_json::Value = serde_json::from_str(&response).unwrap(); + + assert_eq!(response["result"]["type"], "ok"); + assert!(app.state.workspaces.is_empty()); + } + + #[test] fn session_dirty_flag_schedules_debounced_save() { let mut app = test_app(); app.no_session = false; |
