diff options
| author | akbash <akbash@herdr.dev> | 2026-07-06 16:19:31 +0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-07-06 16:19:31 +0300 |
| commit | fbc3f0845a1ad94a739f999b4b1edc1bba4e291a (patch) | |
| tree | 6026b8152de6a410989f478a3786d9e695aba2f1 /src | |
| parent | 90debb9cef1261bccb36c8fea8be86cb95f03b0e (diff) | |
fix: focus parent after worktree removal (#1075)
refs #1004
Co-authored-by: akbash-bot <akbash-bot@users.noreply.github.com>
Diffstat (limited to 'src')
| -rw-r--r-- | src/app/api/worktrees/deferred.rs | 3 | ||||
| -rw-r--r-- | src/app/worktrees.rs | 89 |
2 files changed, 88 insertions, 4 deletions
diff --git a/src/app/api/worktrees/deferred.rs b/src/app/api/worktrees/deferred.rs index 516e9455..3cd5e9f1 100644 --- a/src/app/api/worktrees/deferred.rs +++ b/src/app/api/worktrees/deferred.rs @@ -548,8 +548,7 @@ impl App { .cloned() .map(|space| self.worktree_info_for_membership(&space, None)); } - self.state.selected = ws_idx; - self.state.close_selected_workspace(); + self.close_removed_linked_worktree_workspace(ws_idx); self.shutdown_detached_terminal_runtimes(); self.emit_event(EventEnvelope { event: EventKind::WorkspaceClosed, diff --git a/src/app/worktrees.rs b/src/app/worktrees.rs index ecaa01a4..a61a78ab 100644 --- a/src/app/worktrees.rs +++ b/src/app/worktrees.rs @@ -916,8 +916,7 @@ impl App { space.is_linked_worktree && space.checkout_path == result.path }); if still_same_linked_worktree { - self.state.selected = ws_idx; - self.state.close_selected_workspace(); + self.close_removed_linked_worktree_workspace(ws_idx); self.shutdown_detached_terminal_runtimes(); self.emit_event(crate::api::schema::EventEnvelope { event: crate::api::schema::EventKind::WorkspaceClosed, @@ -969,6 +968,31 @@ impl App { force || cfg!(windows) } + pub(crate) fn close_removed_linked_worktree_workspace(&mut self, ws_idx: usize) { + let parent_key = self + .state + .workspaces + .get(ws_idx) + .and_then(|workspace| workspace.worktree_space()) + .filter(|space| space.is_linked_worktree) + .map(|space| space.key.clone()); + + self.state.selected = ws_idx; + self.state.close_selected_workspace(); + + let Some(parent_key) = parent_key else { + return; + }; + let Some(parent_idx) = self.state.workspaces.iter().position(|workspace| { + workspace + .worktree_space() + .is_some_and(|space| !space.is_linked_worktree && space.key == parent_key) + }) else { + return; + }; + self.state.switch_workspace(parent_idx); + } + pub(crate) fn shutdown_workspace_terminal_runtimes_for_worktree_remove( &mut self, ws_idx: usize, @@ -2144,6 +2168,67 @@ mod tests { } #[test] + fn worktree_remove_finished_focuses_parent_workspace() { + let mut app = app_for_worktree_tests(); + let checkout = std::path::PathBuf::from("/repo/herdr-issue"); + app.state.workspaces = vec![ + crate::workspace::Workspace::test_new("parent"), + crate::workspace::Workspace::test_new("issue"), + crate::workspace::Workspace::test_new("sibling"), + ]; + app.state.workspaces[0].worktree_space = Some(crate::workspace::WorktreeSpaceMembership { + key: "repo-key".into(), + label: "herdr".into(), + repo_root: "/repo/herdr".into(), + checkout_path: "/repo/herdr".into(), + is_linked_worktree: false, + }); + app.state.workspaces[1].worktree_space = Some(crate::workspace::WorktreeSpaceMembership { + key: "repo-key".into(), + label: "herdr".into(), + repo_root: "/repo/herdr".into(), + checkout_path: checkout.clone(), + is_linked_worktree: true, + }); + app.state.workspaces[2].worktree_space = Some(crate::workspace::WorktreeSpaceMembership { + key: "repo-key".into(), + label: "herdr".into(), + repo_root: "/repo/herdr".into(), + checkout_path: "/repo/herdr-sibling".into(), + is_linked_worktree: true, + }); + let child_id = app.state.workspaces[1].id.clone(); + let parent_id = app.state.workspaces[0].id.clone(); + app.state.active = Some(1); + app.state.selected = 1; + app.state.worktree_remove = Some(WorktreeRemoveState { + workspace_id: child_id.clone(), + repo_root: std::path::PathBuf::from("/repo/herdr"), + path: checkout.clone(), + error: None, + removing: true, + force_confirmation: false, + }); + + app.handle_worktree_remove_finished(WorktreeRemoveResult { + workspace_id: child_id, + path: checkout, + workspace: None, + worktree: None, + forced: false, + api_request: None, + result: Ok(()), + }); + + assert_eq!(app.state.workspaces.len(), 2); + assert_eq!(app.state.active, Some(0)); + assert_eq!(app.state.selected, 0); + assert_eq!(app.state.workspaces[0].id, parent_id); + assert_eq!(app.state.workspaces[1].display_name(), "sibling"); + assert!(app.state.worktree_remove.is_none()); + } + + #[test] fn worktree_remove_finished_emits_removed_event_from_snapshot_after_workspace_closed() { let event_hub = crate::api::EventHub::default(); let mut app = app_for_worktree_tests_with_event_hub(event_hub.clone()); |
