@@ -1730,6 +1730,32 @@ impl Sidebar {
},
);
+ let menu = if project_group_key.host().is_none() {
+ menu.entry(
+ "Open Project in New Window",
+ None,
+ {
+ let project_group_key = project_group_key.clone();
+ let multi_workspace = multi_workspace.clone();
+ move |window, cx| {
+ multi_workspace
+ .update(cx, |multi_workspace, cx| {
+ multi_workspace
+ .open_project_group_in_new_window(
+ &project_group_key,
+ window,
+ cx,
+ )
+ .detach_and_log_err(cx);
+ })
+ .ok();
+ }
+ },
+ )
+ } else {
+ menu
+ };
+
let project_group_key = project_group_key.clone();
let multi_workspace = multi_workspace.clone();
let weak_menu = menu_cx.weak_entity();
@@ -854,6 +854,61 @@ impl MultiWorkspace {
)
}
+ /// Goes through sqlite: serialize -> close -> open new window
+ /// This avoids issues with pending tasks having the wrong window
+ pub fn open_project_group_in_new_window(
+ &mut self,
+ key: &ProjectGroupKey,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) -> Task<Result<()>> {
+ let paths: Vec<PathBuf> = key.path_list().ordered_paths().cloned().collect();
+ if paths.is_empty() {
+ return Task::ready(Ok(()));
+ }
+
+ let app_state = self.workspace().read(cx).app_state().clone();
+
+ let workspaces: Vec<_> = self
+ .workspaces_for_project_group(key, cx)
+ .cloned()
+ .collect();
+ let mut serialization_tasks = Vec::new();
+ for workspace in &workspaces {
+ serialization_tasks.push(
+ workspace.update(cx, |workspace, inner_cx| {
+ workspace.flush_serialization(window, inner_cx)
+ }),
+ );
+ }
+
+ let remove_task = self.remove_project_group(key, window, cx);
+
+ cx.spawn(async move |_this, cx| {
+ futures::future::join_all(serialization_tasks).await;
+
+ let removed = remove_task.await?;
+ if !removed {
+ return Ok(());
+ }
+
+ cx.update(|cx| {
+ Workspace::new_local(
+ paths,
+ app_state,
+ None,
+ None,
+ None,
+ OpenMode::NewWindow,
+ cx,
+ )
+ })
+ .await?;
+
+ Ok(())
+ })
+ }
+
/// Finds an existing workspace whose root paths and host exactly match.
pub fn workspace_for_paths(
&self,