sidebar: Fix behavior of "Remove Project" button (#53242)

- Fix an issue where the "remove project" button, available in the
header's ellipsis menu, wouldn't do anything if the sidebar contained
only one project
- Fix another issue where attempting to remove a project when the
sidebar has more than one project wouldn't actually remove it. This is
fixed by cleaning up the project group keys after its been already
removed.

Release Notes:

- N/A
This commit is contained in:
Danilo Leal authored and GitHub committed 2026-04-06 16:34:36 -03:00
1 parent 383b0a7afb
commit 7adbee0cdc
1 file changed
+70 -15
+70 -15
View File
@@ -6,9 +6,7 @@ use gpui::{
ManagedView, MouseButton, Pixels, Render, Subscription, Task, Tiling, Window, WindowId,
actions, deferred, px,
};
#[cfg(any(test, feature = "test-support"))]
use project::Project;
use project::{DirectoryLister, DisableAiSettings, ProjectGroupKey};
use project::{DirectoryLister, DisableAiSettings, Project, ProjectGroupKey};
use settings::Settings;
pub use settings::SidebarSide;
use std::future::Future;
@@ -468,6 +466,9 @@ impl MultiWorkspace {
}
pub fn add_project_group_key(&mut self, project_group_key: ProjectGroupKey) {
if project_group_key.path_list().paths().is_empty() {
return;
}
if self.project_group_keys.contains(&project_group_key) {
return;
}
@@ -1040,26 +1041,80 @@ impl MultiWorkspace {
let Some(index) = self.workspaces.iter().position(|w| w == workspace) else {
return false;
};
let old_key = workspace.read(cx).project_group_key(cx);
if self.workspaces.len() <= 1 {
return false;
let has_worktrees = workspace.read(cx).visible_worktrees(cx).next().is_some();
if !has_worktrees {
return false;
}
let old_workspace = workspace.clone();
let old_entity_id = old_workspace.entity_id();
let app_state = old_workspace.read(cx).app_state().clone();
let project = Project::local(
app_state.client.clone(),
app_state.node_runtime.clone(),
app_state.user_store.clone(),
app_state.languages.clone(),
app_state.fs.clone(),
None,
project::LocalProjectFlags::default(),
cx,
);
let new_workspace = cx.new(|cx| Workspace::new(None, project, app_state, window, cx));
self.workspaces[0] = new_workspace.clone();
self.active_workspace_index = 0;
Self::subscribe_to_workspace(&new_workspace, window, cx);
self.sync_sidebar_to_workspace(&new_workspace, cx);
let weak_self = cx.weak_entity();
new_workspace.update(cx, |workspace, cx| {
workspace.set_multi_workspace(weak_self, cx);
});
self.detach_workspace(&old_workspace, cx);
cx.emit(MultiWorkspaceEvent::WorkspaceRemoved(old_entity_id));
cx.emit(MultiWorkspaceEvent::WorkspaceAdded(new_workspace));
cx.emit(MultiWorkspaceEvent::ActiveWorkspaceChanged);
} else {
let removed_workspace = self.workspaces.remove(index);
if self.active_workspace_index >= self.workspaces.len() {
self.active_workspace_index = self.workspaces.len() - 1;
} else if self.active_workspace_index > index {
self.active_workspace_index -= 1;
}
self.detach_workspace(&removed_workspace, cx);
cx.emit(MultiWorkspaceEvent::WorkspaceRemoved(
removed_workspace.entity_id(),
));
cx.emit(MultiWorkspaceEvent::ActiveWorkspaceChanged);
}
let removed_workspace = self.workspaces.remove(index);
let key_still_in_use = self
.workspaces
.iter()
.any(|ws| ws.read(cx).project_group_key(cx) == old_key);
if self.active_workspace_index >= self.workspaces.len() {
self.active_workspace_index = self.workspaces.len() - 1;
} else if self.active_workspace_index > index {
self.active_workspace_index -= 1;
if !key_still_in_use {
self.project_group_keys.retain(|k| k != &old_key);
}
self.detach_workspace(&removed_workspace, cx);
self.serialize(cx);
self.focus_active_workspace(window, cx);
cx.emit(MultiWorkspaceEvent::WorkspaceRemoved(
removed_workspace.entity_id(),
));
cx.emit(MultiWorkspaceEvent::ActiveWorkspaceChanged);
cx.notify();
true