diff --git a/Cargo.lock b/Cargo.lock index 939fee5989fec75d579d762a42c40869537c6c36..6d2bc86decb9438e8b7c4dd9a61755207c5861c3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7151,6 +7151,7 @@ dependencies = [ "ordered-float 2.10.0", "picker", "project", + "serde", "serde_json", "smol", "ui", diff --git a/assets/keymaps/default-linux.json b/assets/keymaps/default-linux.json index feeb0f081b86a6412fafc48df6e88bedab685c15..9beceba3793c733b7612a149848173dca6e12a16 100644 --- a/assets/keymaps/default-linux.json +++ b/assets/keymaps/default-linux.json @@ -341,6 +341,13 @@ { "context": "Workspace", "bindings": { + // Change the default action on `menu::Confirm` by setting the parameter + // "alt-cmd-o": [ + // "projects::OpenRecent", + // { + // "create_new_window": true + // } + // ] "ctrl-alt-o": "projects::OpenRecent", "ctrl-alt-b": "branches::OpenRecent", "ctrl-~": "workspace::NewTerminal", diff --git a/assets/keymaps/default-macos.json b/assets/keymaps/default-macos.json index f12eff73e8e18e2e562697907ba0cfc8f9303819..60d9b598dd3a8c2bcea623497aac10b5131e2701 100644 --- a/assets/keymaps/default-macos.json +++ b/assets/keymaps/default-macos.json @@ -383,6 +383,13 @@ { "context": "Workspace", "bindings": { + // Change the default action on `menu::Confirm` by setting the parameter + // "alt-cmd-o": [ + // "projects::OpenRecent", + // { + // "create_new_window": true + // } + // ] "alt-cmd-o": "projects::OpenRecent", "alt-cmd-b": "branches::OpenRecent", "ctrl-~": "workspace::NewTerminal", diff --git a/crates/recent_projects/Cargo.toml b/crates/recent_projects/Cargo.toml index eb5638d53e55cedf592ca88f07720d97c1b3050a..f96dfbdd7db8487af438f553d18bfff5f42eb6c9 100644 --- a/crates/recent_projects/Cargo.toml +++ b/crates/recent_projects/Cargo.toml @@ -15,6 +15,7 @@ gpui.workspace = true menu.workspace = true ordered-float.workspace = true picker.workspace = true +serde.workspace = true smol.workspace = true ui.workspace = true util.workspace = true diff --git a/crates/recent_projects/src/recent_projects.rs b/crates/recent_projects/src/recent_projects.rs index 1c284952765c353b37bd5e74d641188e4a8c5fb9..3c359dce9f7d8c1b7e33ac607a4afd76ea47a90e 100644 --- a/crates/recent_projects/src/recent_projects.rs +++ b/crates/recent_projects/src/recent_projects.rs @@ -8,12 +8,19 @@ use gpui::{ use highlighted_workspace_location::HighlightedWorkspaceLocation; use ordered_float::OrderedFloat; use picker::{Picker, PickerDelegate}; +use serde::Deserialize; use std::sync::Arc; use ui::{prelude::*, tooltip_container, HighlightedLabel, ListItem, ListItemSpacing, Tooltip}; use util::paths::PathExt; use workspace::{ModalView, Workspace, WorkspaceId, WorkspaceLocation, WORKSPACE_DB}; -gpui::actions!(projects, [OpenRecent]); +#[derive(PartialEq, Clone, Deserialize, Default)] +pub struct OpenRecent { + #[serde(default)] + pub create_new_window: bool, +} + +gpui::impl_actions!(projects, [OpenRecent]); pub fn init(cx: &mut AppContext) { cx.observe_new_views(RecentProjects::register).detach(); @@ -63,9 +70,9 @@ impl RecentProjects { } fn register(workspace: &mut Workspace, _: &mut ViewContext) { - workspace.register_action(|workspace, _: &OpenRecent, cx| { + workspace.register_action(|workspace, open_recent: &OpenRecent, cx| { let Some(recent_projects) = workspace.active_modal::(cx) else { - if let Some(handler) = Self::open(workspace, cx) { + if let Some(handler) = Self::open(workspace, open_recent.create_new_window, cx) { handler.detach_and_log_err(cx); } return; @@ -79,12 +86,17 @@ impl RecentProjects { }); } - fn open(_: &mut Workspace, cx: &mut ViewContext) -> Option>> { + fn open( + _: &mut Workspace, + create_new_window: bool, + cx: &mut ViewContext, + ) -> Option>> { Some(cx.spawn(|workspace, mut cx| async move { workspace.update(&mut cx, |workspace, cx| { let weak_workspace = cx.view().downgrade(); workspace.toggle_modal(cx, |cx| { - let delegate = RecentProjectsDelegate::new(weak_workspace, true); + let delegate = + RecentProjectsDelegate::new(weak_workspace, create_new_window, true); let modal = Self::new(delegate, 34., cx); modal @@ -95,7 +107,13 @@ impl RecentProjects { } pub fn open_popover(workspace: WeakView, cx: &mut WindowContext<'_>) -> View { - cx.new_view(|cx| Self::new(RecentProjectsDelegate::new(workspace, false), 20., cx)) + cx.new_view(|cx| { + Self::new( + RecentProjectsDelegate::new(workspace, false, false), + 20., + cx, + ) + }) } } @@ -126,17 +144,19 @@ pub struct RecentProjectsDelegate { selected_match_index: usize, matches: Vec, render_paths: bool, + create_new_window: bool, // Flag to reset index when there is a new query vs not reset index when user delete an item reset_selected_match_index: bool, } impl RecentProjectsDelegate { - fn new(workspace: WeakView, render_paths: bool) -> Self { + fn new(workspace: WeakView, create_new_window: bool, render_paths: bool) -> Self { Self { workspace, workspaces: vec![], selected_match_index: 0, matches: Default::default(), + create_new_window, render_paths, reset_selected_match_index: true, } @@ -147,10 +167,19 @@ impl PickerDelegate for RecentProjectsDelegate { type ListItem = ListItem; fn placeholder_text(&self, cx: &mut WindowContext) -> Arc { + let (create_window, reuse_window) = if self.create_new_window { + ( + cx.keystroke_text_for(&menu::Confirm), + cx.keystroke_text_for(&menu::SecondaryConfirm), + ) + } else { + ( + cx.keystroke_text_for(&menu::SecondaryConfirm), + cx.keystroke_text_for(&menu::Confirm), + ) + }; Arc::from(format!( - "{} reuses the window, {} opens a new one", - cx.keystroke_text_for(&menu::Confirm), - cx.keystroke_text_for(&menu::SecondaryConfirm), + "{reuse_window} reuses the window, {create_window} opens a new one", )) } @@ -219,7 +248,11 @@ impl PickerDelegate for RecentProjectsDelegate { { let (candidate_workspace_id, candidate_workspace_location) = &self.workspaces[selected_match.candidate_id]; - let replace_current_window = !secondary; + let replace_current_window = if self.create_new_window { + secondary + } else { + !secondary + }; workspace .update(cx, |workspace, cx| { if workspace.database_id() != *candidate_workspace_id { @@ -492,7 +525,12 @@ mod tests { workspace: &WindowHandle, cx: &mut TestAppContext, ) -> View> { - cx.dispatch_action((*workspace).into(), OpenRecent); + cx.dispatch_action( + (*workspace).into(), + OpenRecent { + create_new_window: false, + }, + ); workspace .update(cx, |workspace, cx| { workspace diff --git a/crates/zed/src/app_menus.rs b/crates/zed/src/app_menus.rs index 0ea51801eae88de181d624b9b3704a8d5075a7fd..43b1d45c15018026d219ca24d4c2f42231179ad1 100644 --- a/crates/zed/src/app_menus.rs +++ b/crates/zed/src/app_menus.rs @@ -37,7 +37,12 @@ pub fn app_menus() -> Vec> { MenuItem::action("New Window", workspace::NewWindow), MenuItem::separator(), MenuItem::action("Open…", workspace::Open), - MenuItem::action("Open Recent...", recent_projects::OpenRecent), + MenuItem::action( + "Open Recent...", + recent_projects::OpenRecent { + create_new_window: false, + }, + ), MenuItem::separator(), MenuItem::action("Add Folder to Project…", workspace::AddFolderToProject), MenuItem::action("Save", workspace::Save { save_intent: None }),