workspace: Do not reuse window for sub directory (only for root directory and sub files) (#24560)

Closes #10232

Context:

We have three ways to open files or dirs in Zed: `zed`, `zed --new`, and
`zed --add`. `--new` forces the project to open in a new window, while
`--add` forces it to open in an existing window (even if the dir isn’t a
subdir of an existing project or the file isn’t part of it).

Using just `zed` tries to open it in an existing window based on similar
logic of `--add`, but if no related project is found the dir, opens in a
new window.

Problem:

Right now, subdirs that are part of an existing project open in the
existing window when using `zed`. By default, subdirs should open in a
new window instead. If someone wants to open it in the existing window,
they can explicitly use `--add`. After this PR, only root dir and files
will focus on existing window, when `zed ` is used.

Fix:

For the `zed` case, we’ve filtered out subdirs in the logic that assigns
them to an existing window.

Release Notes:

- Fixed an issue where subdirectories of an already opened project, when
opened via the terminal, would open in the existing project instead of a
new window.
This commit is contained in:
smit 2025-02-13 03:37:39 +05:30 committed by GitHub
parent c771ca49e1
commit 5dc3c237eb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 77 additions and 58 deletions

View file

@ -5958,7 +5958,6 @@ pub struct OpenOptions {
pub replace_window: Option<WindowHandle<Workspace>>,
pub env: Option<HashMap<String, String>>,
}
#[allow(clippy::type_complexity)]
pub fn open_paths(
abs_paths: &[PathBuf],
@ -5976,58 +5975,65 @@ pub fn open_paths(
let mut best_match = None;
let mut open_visible = OpenVisible::All;
if open_options.open_new_workspace != Some(true) {
for window in local_workspace_windows(cx) {
if let Ok(workspace) = window.read(cx) {
let m = workspace
.project
.read(cx)
.visibility_for_paths(&abs_paths, cx);
if m > best_match {
existing = Some(window);
best_match = m;
} else if best_match.is_none() && open_options.open_new_workspace == Some(false) {
existing = Some(window)
}
}
}
}
cx.spawn(move |mut cx| async move {
if open_options.open_new_workspace.is_none() && existing.is_none() {
let all_files = abs_paths.iter().map(|path| app_state.fs.metadata(path));
if futures::future::join_all(all_files)
if open_options.open_new_workspace != Some(true) {
let all_paths = abs_paths.iter().map(|path| app_state.fs.metadata(path));
let all_metadatas = futures::future::join_all(all_paths)
.await
.into_iter()
.filter_map(|result| result.ok().flatten())
.all(|file| !file.is_dir)
{
cx.update(|cx| {
if let Some(window) = cx
.active_window()
.and_then(|window| window.downcast::<Workspace>())
{
if let Ok(workspace) = window.read(cx) {
let project = workspace.project().read(cx);
if project.is_local() && !project.is_via_collab() {
.collect::<Vec<_>>();
cx.update(|cx| {
for window in local_workspace_windows(&cx) {
if let Ok(workspace) = window.read(&cx) {
let m = workspace.project.read(&cx).visibility_for_paths(
&abs_paths,
&all_metadatas,
open_options.open_new_workspace == None,
cx,
);
if m > best_match {
existing = Some(window);
best_match = m;
} else if best_match.is_none()
&& open_options.open_new_workspace == Some(false)
{
existing = Some(window)
}
}
}
})?;
if open_options.open_new_workspace.is_none() && existing.is_none() {
if all_metadatas.iter().all(|file| !file.is_dir) {
cx.update(|cx| {
if let Some(window) = cx
.active_window()
.and_then(|window| window.downcast::<Workspace>())
{
if let Ok(workspace) = window.read(cx) {
let project = workspace.project().read(cx);
if project.is_local() && !project.is_via_collab() {
existing = Some(window);
open_visible = OpenVisible::None;
return;
}
}
}
for window in local_workspace_windows(cx) {
if let Ok(workspace) = window.read(cx) {
let project = workspace.project().read(cx);
if project.is_via_collab() {
continue;
}
existing = Some(window);
open_visible = OpenVisible::None;
return;
break;
}
}
}
for window in local_workspace_windows(cx) {
if let Ok(workspace) = window.read(cx) {
let project = workspace.project().read(cx);
if project.is_via_collab() {
continue;
}
existing = Some(window);
open_visible = OpenVisible::None;
break;
}
}
})?;
})?;
}
}
}