diff --git a/Cargo.lock b/Cargo.lock index af335bce67..506f8f6788 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7343,6 +7343,7 @@ dependencies = [ "fuzzy", "gpui", "language", + "menu", "ordered-float 2.10.0", "picker", "postage", diff --git a/crates/recent_projects/Cargo.toml b/crates/recent_projects/Cargo.toml index 48e3cff72d..600a144f13 100644 --- a/crates/recent_projects/Cargo.toml +++ b/crates/recent_projects/Cargo.toml @@ -15,6 +15,7 @@ futures.workspace = true fuzzy.workspace = true gpui.workspace = true language.workspace = true +menu.workspace = true ordered-float.workspace = true picker.workspace = true postage.workspace = true diff --git a/crates/recent_projects/src/projects.rs b/crates/recent_projects/src/projects.rs deleted file mode 100644 index d9cfbd08ad..0000000000 --- a/crates/recent_projects/src/projects.rs +++ /dev/null @@ -1 +0,0 @@ -gpui::actions!(projects, [OpenRecent]); diff --git a/crates/recent_projects/src/recent_projects.rs b/crates/recent_projects/src/recent_projects.rs index ac15c08eb6..db4e73d6b2 100644 --- a/crates/recent_projects/src/recent_projects.rs +++ b/crates/recent_projects/src/recent_projects.rs @@ -1,5 +1,4 @@ mod highlighted_workspace_location; -mod projects; use fuzzy::{StringMatch, StringMatchCandidate}; use gpui::{ @@ -14,7 +13,7 @@ use ui::{prelude::*, tooltip_container, HighlightedLabel, ListItem, ListItemSpac use util::paths::PathExt; use workspace::{ModalView, Workspace, WorkspaceId, WorkspaceLocation, WORKSPACE_DB}; -pub use projects::OpenRecent; +gpui::actions!(projects, [OpenRecent]); pub fn init(cx: &mut AppContext) { cx.observe_new_views(RecentProjects::register).detach(); @@ -94,6 +93,7 @@ impl RecentProjects { Ok(()) })) } + pub fn open_popover(workspace: WeakView, cx: &mut WindowContext<'_>) -> View { cx.new_view(|cx| Self::new(RecentProjectsDelegate::new(workspace, false), 20., cx)) } @@ -147,7 +147,11 @@ impl PickerDelegate for RecentProjectsDelegate { type ListItem = ListItem; fn placeholder_text(&self) -> Arc { - "Search recent projects...".into() + Arc::from(format!( + "`{:?}` reuses the window, `{:?}` opens in new", + menu::Confirm, + menu::SecondaryConfirm, + )) } fn match_count(&self) -> usize { @@ -207,17 +211,26 @@ impl PickerDelegate for RecentProjectsDelegate { Task::ready(()) } - fn confirm(&mut self, _: bool, cx: &mut ViewContext>) { + fn confirm(&mut self, secondary: bool, cx: &mut ViewContext>) { if let Some((selected_match, workspace)) = self .matches .get(self.selected_index()) .zip(self.workspace.upgrade()) { - let (_, workspace_location) = &self.workspaces[selected_match.candidate_id]; + let (candidate_workspace_id, candidate_workspace_location) = + &self.workspaces[selected_match.candidate_id]; + let replace_current_window = !secondary; workspace .update(cx, |workspace, cx| { - workspace - .open_workspace_for_paths(workspace_location.paths().as_ref().clone(), cx) + if workspace.database_id() != *candidate_workspace_id { + workspace.open_workspace_for_paths( + replace_current_window, + candidate_workspace_location.paths().as_ref().clone(), + cx, + ) + } else { + Task::ready(Ok(())) + } }) .detach_and_log_err(cx); cx.emit(DismissEvent); diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 77b99f76c5..2df22dcea1 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -1387,7 +1387,9 @@ impl Workspace { }; if let Some(task) = this - .update(&mut cx, |this, cx| this.open_workspace_for_paths(paths, cx)) + .update(&mut cx, |this, cx| { + this.open_workspace_for_paths(false, paths, cx) + }) .log_err() { task.await.log_err(); @@ -1398,6 +1400,7 @@ impl Workspace { pub fn open_workspace_for_paths( &mut self, + replace_current_window: bool, paths: Vec, cx: &mut ViewContext, ) -> Task> { @@ -1405,7 +1408,10 @@ impl Workspace { let is_remote = self.project.read(cx).is_remote(); let has_worktree = self.project.read(cx).worktrees().next().is_some(); let has_dirty_items = self.items(cx).any(|item| item.is_dirty(cx)); - let window_to_replace = if is_remote || has_worktree || has_dirty_items { + + let window_to_replace = if replace_current_window { + window + } else if is_remote || has_worktree || has_dirty_items { None } else { window