diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 79586f2615d5918b230ed5c1c6f2314770ee04b0..f38bca1c479c4679e717cb21ffda7127cab05987 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -1699,63 +1699,70 @@ impl Workspace { let prompt = self.on_prompt_for_new_path.take().unwrap(); let rx = prompt(self, window, cx); self.on_prompt_for_new_path = Some(prompt); - rx - } else { - let start_abs_path = self - .project - .update(cx, |project, cx| { - let worktree = project.visible_worktrees(cx).next()?; - Some(worktree.read(cx).as_local()?.abs_path().to_path_buf()) - }) - .unwrap_or_else(|| Path::new("").into()); + return rx; + } - let (tx, rx) = oneshot::channel(); - let abs_path = cx.prompt_for_new_path(&start_abs_path); - cx.spawn_in(window, async move |this, cx| { - let abs_path = match abs_path.await? { - Ok(path) => path, - Err(err) => { - let rx = this.update_in(cx, |this, window, cx| { - this.show_portal_error(err.to_string(), cx); + let (tx, rx) = oneshot::channel(); + cx.spawn_in(window, async move |this, cx| { + let abs_path = this.update(cx, |this, cx| { + let mut relative_to = this + .most_recent_active_path(cx) + .and_then(|p| p.parent().map(|p| p.to_path_buf())); + if relative_to.is_none() { + let project = this.project.read(cx); + relative_to = project + .visible_worktrees(cx) + .filter_map(|worktree| { + Some(worktree.read(cx).as_local()?.abs_path().to_path_buf()) + }) + .next() + }; - let prompt = this.on_prompt_for_new_path.take().unwrap(); - let rx = prompt(this, window, cx); - this.on_prompt_for_new_path = Some(prompt); - rx - })?; - if let Ok(path) = rx.await { - tx.send(path).log_err(); - } - return anyhow::Ok(()); + cx.prompt_for_new_path(&relative_to.unwrap_or_else(|| PathBuf::from(""))) + })?; + let abs_path = match abs_path.await? { + Ok(path) => path, + Err(err) => { + let rx = this.update_in(cx, |this, window, cx| { + this.show_portal_error(err.to_string(), cx); + + let prompt = this.on_prompt_for_new_path.take().unwrap(); + let rx = prompt(this, window, cx); + this.on_prompt_for_new_path = Some(prompt); + rx + })?; + if let Ok(path) = rx.await { + tx.send(path).log_err(); } - }; + return anyhow::Ok(()); + } + }; - let project_path = abs_path.and_then(|abs_path| { - this.update(cx, |this, cx| { - this.project.update(cx, |project, cx| { - project.find_or_create_worktree(abs_path, true, cx) - }) + let project_path = abs_path.and_then(|abs_path| { + this.update(cx, |this, cx| { + this.project.update(cx, |project, cx| { + project.find_or_create_worktree(abs_path, true, cx) }) - .ok() - }); + }) + .ok() + }); - if let Some(project_path) = project_path { - let (worktree, path) = project_path.await?; - let worktree_id = worktree.read_with(cx, |worktree, _| worktree.id())?; - tx.send(Some(ProjectPath { - worktree_id, - path: path.into(), - })) - .ok(); - } else { - tx.send(None).ok(); - } - anyhow::Ok(()) - }) - .detach_and_log_err(cx); + if let Some(project_path) = project_path { + let (worktree, path) = project_path.await?; + let worktree_id = worktree.read_with(cx, |worktree, _| worktree.id())?; + tx.send(Some(ProjectPath { + worktree_id, + path: path.into(), + })) + .ok(); + } else { + tx.send(None).ok(); + } + anyhow::Ok(()) + }) + .detach_and_log_err(cx); - rx - } + rx } pub fn titlebar_item(&self) -> Option { @@ -2356,6 +2363,22 @@ impl Workspace { self.active_item(cx).and_then(|item| item.project_path(cx)) } + pub fn most_recent_active_path(&self, cx: &App) -> Option { + self.recent_navigation_history_iter(cx) + .filter_map(|(path, abs_path)| { + let worktree = self + .project + .read(cx) + .worktree_for_id(path.worktree_id, cx)?; + if worktree.read(cx).is_visible() { + abs_path + } else { + None + } + }) + .next() + } + pub fn save_active_item( &mut self, save_intent: SaveIntent,