sidebar: Move to new window, going through sqlite (#53513)
Re-adds the `multi_workspace::MoveProjectToNewWindow` action It serializes, then closes, then re-opens the project to avoid issues with pending tasks Release Notes: - N/A or Added/Fixed/Improved ...
This commit is contained in:
1 parent
412683f52d
commit
35566bca98
3 files changed
+95
-9
No files matched your search
@@ -1972,6 +1972,10 @@ impl Sidebar {
|
||||
let multi_workspace = multi_workspace.clone();
|
||||
let project_group_key = project_group_key.clone();
|
||||
|
||||
let has_multiple_projects = multi_workspace
|
||||
.read_with(cx, |mw, _| mw.project_group_keys().len() >= 2)
|
||||
.unwrap_or(false);
|
||||
|
||||
let menu =
|
||||
ContextMenu::build_persistent(window, cx, move |menu, _window, menu_cx| {
|
||||
let weak_menu = menu_cx.weak_entity();
|
||||
@@ -2031,6 +2035,32 @@ impl Sidebar {
|
||||
},
|
||||
);
|
||||
|
||||
let menu = if project_group_key.host().is_none() && has_multiple_projects {
|
||||
menu.entry(
|
||||
"Open Project in New Window",
|
||||
Some(Box::new(workspace::MoveProjectToNewWindow)),
|
||||
{
|
||||
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();
|
||||
menu.separator()
|
||||
|
||||
@@ -54,6 +54,8 @@ actions!(
|
||||
ShowFewerThreads,
|
||||
/// Creates a new thread in the current workspace.
|
||||
NewThread,
|
||||
/// Moves the active project to a new window.
|
||||
MoveProjectToNewWindow,
|
||||
]
|
||||
);
|
||||
|
||||
@@ -1017,6 +1019,50 @@ 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)
|
||||
.unwrap_or_default();
|
||||
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,
|
||||
@@ -1836,13 +1882,23 @@ impl Render for MultiWorkspace {
|
||||
sidebar.cycle_thread(true, window, cx);
|
||||
}
|
||||
}))
|
||||
.on_action(cx.listener(
|
||||
|this: &mut Self, _: &PreviousThread, window, cx| {
|
||||
.on_action(
|
||||
cx.listener(|this: &mut Self, _: &PreviousThread, window, cx| {
|
||||
if let Some(sidebar) = &this.sidebar {
|
||||
sidebar.cycle_thread(false, window, cx);
|
||||
}
|
||||
},
|
||||
))
|
||||
}),
|
||||
)
|
||||
.when(self.project_group_keys().len() >= 2, |el| {
|
||||
el.on_action(cx.listener(
|
||||
|this: &mut Self, _: &MoveProjectToNewWindow, window, cx| {
|
||||
let key =
|
||||
this.project_group_key_for_workspace(this.workspace(), cx);
|
||||
this.open_project_group_in_new_window(&key, window, cx)
|
||||
.detach_and_log_err(cx);
|
||||
},
|
||||
))
|
||||
})
|
||||
})
|
||||
.when(
|
||||
self.sidebar_open() && self.multi_workspace_enabled(cx),
|
||||
|
||||
@@ -31,11 +31,11 @@ mod workspace_settings;
|
||||
pub use crate::notifications::NotificationFrame;
|
||||
pub use dock::Panel;
|
||||
pub use multi_workspace::{
|
||||
CloseWorkspaceSidebar, DraggedSidebar, FocusWorkspaceSidebar, MultiWorkspace,
|
||||
MultiWorkspaceEvent, NewThread, NextProject, NextThread, PreviousProject, PreviousThread,
|
||||
ProjectGroup, ProjectGroupKey, SerializedProjectGroupState, ShowFewerThreads, ShowMoreThreads,
|
||||
Sidebar, SidebarEvent, SidebarHandle, SidebarRenderState, SidebarSide, ToggleWorkspaceSidebar,
|
||||
sidebar_side_context_menu,
|
||||
CloseWorkspaceSidebar, DraggedSidebar, FocusWorkspaceSidebar, MoveProjectToNewWindow,
|
||||
MultiWorkspace, MultiWorkspaceEvent, NewThread, NextProject, NextThread, PreviousProject,
|
||||
PreviousThread, ProjectGroup, ProjectGroupKey, SerializedProjectGroupState, ShowFewerThreads,
|
||||
ShowMoreThreads, Sidebar, SidebarEvent, SidebarHandle, SidebarRenderState, SidebarSide,
|
||||
ToggleWorkspaceSidebar, sidebar_side_context_menu,
|
||||
};
|
||||
pub use path_list::{PathList, SerializedPathList};
|
||||
pub use toast_layer::{ToastAction, ToastLayer, ToastView};
|
||||
|
||||
Reference in new issue
Block a user