@@ -1477,7 +1477,7 @@ impl Sidebar {
let workspace_for_add = workspace.clone();
let multi_workspace_for_add = multi_workspace.clone();
- menu.separator().entry(
+ let menu = menu.separator().entry(
"Add Folder to Project",
Some(Box::new(AddFolderToProject)),
move |window, cx| {
@@ -1490,7 +1490,37 @@ impl Sidebar {
workspace.add_folder_to_project(&AddFolderToProject, window, cx);
});
},
- )
+ );
+
+ let workspace_count = multi_workspace
+ .upgrade()
+ .map_or(0, |mw| mw.read(cx).workspaces().len());
+ if workspace_count > 1 {
+ let workspace_for_move = workspace.clone();
+ let multi_workspace_for_move = multi_workspace.clone();
+ menu.entry(
+ "Move to New Window",
+ Some(Box::new(
+ zed_actions::agents_sidebar::MoveWorkspaceToNewWindow,
+ )),
+ move |window, cx| {
+ if let Some(mw) = multi_workspace_for_move.upgrade() {
+ mw.update(cx, |multi_workspace, cx| {
+ if let Some(index) = multi_workspace
+ .workspaces()
+ .iter()
+ .position(|w| *w == workspace_for_move)
+ {
+ multi_workspace
+ .move_workspace_to_new_window(index, window, cx);
+ }
+ });
+ }
+ },
+ )
+ } else {
+ menu
+ }
});
let this = this.clone();
@@ -11,8 +11,10 @@ use project::Project;
use settings::Settings;
use std::future::Future;
use std::path::PathBuf;
+use std::sync::Arc;
use ui::prelude::*;
use util::ResultExt;
+use zed_actions::agents_sidebar::MoveWorkspaceToNewWindow;
const SIDEBAR_RESIZE_HANDLE_SIZE: Pixels = px(6.0);
@@ -671,6 +673,66 @@ impl MultiWorkspace {
cx.notify();
}
+ pub fn move_workspace_to_new_window(
+ &mut self,
+ index: usize,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
+ if self.workspaces.len() <= 1 || index >= self.workspaces.len() {
+ return;
+ }
+
+ let is_active = index == self.active_workspace_index;
+ let workspace = &self.workspaces[index];
+ let paths: Vec<PathBuf> = workspace
+ .read(cx)
+ .worktrees(cx)
+ .map(|worktree| worktree.read(cx).abs_path().to_path_buf())
+ .collect();
+ let app_state: Arc<crate::AppState> = workspace.read(cx).app_state().clone();
+
+ self.remove_workspace(index, window, cx);
+
+ let open_task = cx.spawn(async move |_, cx| {
+ let open_result = cx
+ .update(|cx| {
+ crate::open_paths(
+ &paths,
+ app_state,
+ crate::OpenOptions {
+ open_new_workspace: Some(true),
+ ..Default::default()
+ },
+ cx,
+ )
+ })
+ .await?;
+
+ if is_active {
+ open_result
+ .window
+ .update(cx, |_, window, _cx| {
+ window.activate_window();
+ })
+ .log_err();
+ }
+
+ anyhow::Ok(())
+ });
+ open_task.detach_and_log_err(cx);
+ }
+
+ fn move_active_workspace_to_new_window(
+ &mut self,
+ _: &MoveWorkspaceToNewWindow,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
+ let index = self.active_workspace_index;
+ self.move_workspace_to_new_window(index, window, cx);
+ }
+
pub fn open_project(
&mut self,
paths: Vec<PathBuf>,
@@ -789,6 +851,7 @@ impl Render for MultiWorkspace {
))
.on_action(cx.listener(Self::next_workspace))
.on_action(cx.listener(Self::previous_workspace))
+ .on_action(cx.listener(Self::move_active_workspace_to_new_window))
})
.when(
self.sidebar_open() && self.multi_workspace_enabled(cx),
@@ -786,6 +786,8 @@ pub mod agents_sidebar {
[
/// Moves focus to the sidebar's search/filter editor.
FocusSidebarFilter,
+ /// Moves the active workspace to a new window.
+ MoveWorkspaceToNewWindow,
]
);
}