Add a way to change what menu::Confirm
does in the recent projects modal (#8688)
Follow-up of https://github.com/zed-industries/zed/issues/8651#issuecomment-1973411072 Zed current default is still to reuse the current window, but now it's possible to do ```json "alt-cmd-o": [ "projects::OpenRecent", { "create_new_window": true } ] ``` and change this. menu::Secondary confirm does the action with opposite window creation strategy. Release Notes: - Improved open recent projects flexibility: settings can change whether `menu::Confirm` opens a new window or reuses the old one
This commit is contained in:
parent
37f7957826
commit
3efb871cd4
6 changed files with 72 additions and 13 deletions
|
@ -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
|
||||
|
|
|
@ -8,12 +8,19 @@ use picker::{
|
|||
highlighted_match_with_paths::{HighlightedMatchWithPaths, HighlightedText},
|
||||
Picker, PickerDelegate,
|
||||
};
|
||||
use serde::Deserialize;
|
||||
use std::{path::Path, sync::Arc};
|
||||
use ui::{prelude::*, tooltip_container, 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>) {
|
||||
workspace.register_action(|workspace, _: &OpenRecent, cx| {
|
||||
workspace.register_action(|workspace, open_recent: &OpenRecent, cx| {
|
||||
let Some(recent_projects) = workspace.active_modal::<Self>(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<Workspace>) -> Option<Task<Result<()>>> {
|
||||
fn open(
|
||||
_: &mut Workspace,
|
||||
create_new_window: bool,
|
||||
cx: &mut ViewContext<Workspace>,
|
||||
) -> Option<Task<Result<()>>> {
|
||||
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<Workspace>, cx: &mut WindowContext<'_>) -> View<Self> {
|
||||
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,
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -127,17 +145,19 @@ pub struct RecentProjectsDelegate {
|
|||
selected_match_index: usize,
|
||||
matches: Vec<StringMatch>,
|
||||
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<Workspace>, render_paths: bool) -> Self {
|
||||
fn new(workspace: WeakView<Workspace>, 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,
|
||||
}
|
||||
|
@ -148,10 +168,19 @@ impl PickerDelegate for RecentProjectsDelegate {
|
|||
type ListItem = ListItem;
|
||||
|
||||
fn placeholder_text(&self, cx: &mut WindowContext) -> Arc<str> {
|
||||
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",
|
||||
))
|
||||
}
|
||||
|
||||
|
@ -220,7 +249,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 {
|
||||
|
@ -539,7 +572,12 @@ mod tests {
|
|||
workspace: &WindowHandle<Workspace>,
|
||||
cx: &mut TestAppContext,
|
||||
) -> View<Picker<RecentProjectsDelegate>> {
|
||||
cx.dispatch_action((*workspace).into(), OpenRecent);
|
||||
cx.dispatch_action(
|
||||
(*workspace).into(),
|
||||
OpenRecent {
|
||||
create_new_window: false,
|
||||
},
|
||||
);
|
||||
workspace
|
||||
.update(cx, |workspace, cx| {
|
||||
workspace
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue