diff --git a/crates/sidebar/src/sidebar.rs b/crates/sidebar/src/sidebar.rs index f79cc99c651f2a80815629d5c56a6e4e95f90a5d..692844a37e96905f0458d19435c58598fd0d7faf 100644 --- a/crates/sidebar/src/sidebar.rs +++ b/crates/sidebar/src/sidebar.rs @@ -1314,6 +1314,44 @@ impl Sidebar { }); } + fn close_all_projects(&mut self, window: &mut Window, cx: &mut Context) { + let Some(multi_workspace) = self.multi_workspace.upgrade() else { + return; + }; + + let workspace_count = multi_workspace.read(cx).workspaces().len(); + let active_index = multi_workspace.read(cx).active_workspace_index(); + + // Remove all workspaces except the active one, iterating in reverse + // so that indices of not-yet-visited workspaces remain valid. + for index in (0..workspace_count).rev() { + if index != active_index { + multi_workspace.update(cx, |multi_workspace, cx| { + multi_workspace.remove_workspace(index, window, cx); + }); + } + } + + // Remove all worktrees from the remaining workspace so it becomes empty. + let workspace = multi_workspace.read(cx).workspace().clone(); + let worktree_ids: Vec<_> = workspace + .read(cx) + .project() + .read(cx) + .visible_worktrees(cx) + .map(|worktree| worktree.read(cx).id()) + .collect(); + + workspace.update(cx, |workspace, cx| { + let project = workspace.project().clone(); + project.update(cx, |project, cx| { + for worktree_id in worktree_ids { + project.remove_worktree(worktree_id, cx); + } + }); + }); + } + fn toggle_collapse( &mut self, path_list: &PathList, @@ -1913,6 +1951,22 @@ impl Sidebar { ) -> impl IntoElement { let has_query = self.has_filter_query(cx); let needs_traffic_light_padding = cfg!(target_os = "macos") && !window.is_fullscreen(); + let has_open_projects = self + .multi_workspace + .upgrade() + .map(|mw| { + let mw = mw.read(cx); + mw.workspaces().len() > 1 + || mw + .workspace() + .read(cx) + .project() + .read(cx) + .visible_worktrees(cx) + .next() + .is_some() + }) + .unwrap_or(false); v_flex() .flex_none() @@ -1948,6 +2002,16 @@ impl Sidebar { })), ) }) + .when(has_open_projects, |this| { + this.child( + IconButton::new("close-all-projects", IconName::Exit) + .icon_size(IconSize::Small) + .tooltip(Tooltip::text("Close All Projects")) + .on_click(cx.listener(|this, _, window, cx| { + this.close_all_projects(window, cx); + })), + ) + }) .child( IconButton::new("archive", IconName::Archive) .icon_size(IconSize::Small)