Adjust "recent projects" modal behavior to allow opening projects in both current and new window (#8267)
 Fixes https://github.com/zed-industries/zed/issues/7419 by changing the way "recent projects" modal confirm actions work: * `menu::Confirm` now reuses the current window when opening a recent project * `menu::SecondaryConfirm` now opens a recent project in the new window * neither confirm tries to open the current project anymore * modal's placeholder is adjusted to emphasize this behavior Release Notes: - Added a way to open recent projects in the new window
This commit is contained in:
parent
a588f674db
commit
71557f3eb3
5 changed files with 30 additions and 10 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -7343,6 +7343,7 @@ dependencies = [
|
||||||
"fuzzy",
|
"fuzzy",
|
||||||
"gpui",
|
"gpui",
|
||||||
"language",
|
"language",
|
||||||
|
"menu",
|
||||||
"ordered-float 2.10.0",
|
"ordered-float 2.10.0",
|
||||||
"picker",
|
"picker",
|
||||||
"postage",
|
"postage",
|
||||||
|
|
|
@ -15,6 +15,7 @@ futures.workspace = true
|
||||||
fuzzy.workspace = true
|
fuzzy.workspace = true
|
||||||
gpui.workspace = true
|
gpui.workspace = true
|
||||||
language.workspace = true
|
language.workspace = true
|
||||||
|
menu.workspace = true
|
||||||
ordered-float.workspace = true
|
ordered-float.workspace = true
|
||||||
picker.workspace = true
|
picker.workspace = true
|
||||||
postage.workspace = true
|
postage.workspace = true
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
gpui::actions!(projects, [OpenRecent]);
|
|
|
@ -1,5 +1,4 @@
|
||||||
mod highlighted_workspace_location;
|
mod highlighted_workspace_location;
|
||||||
mod projects;
|
|
||||||
|
|
||||||
use fuzzy::{StringMatch, StringMatchCandidate};
|
use fuzzy::{StringMatch, StringMatchCandidate};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
|
@ -14,7 +13,7 @@ use ui::{prelude::*, tooltip_container, HighlightedLabel, ListItem, ListItemSpac
|
||||||
use util::paths::PathExt;
|
use util::paths::PathExt;
|
||||||
use workspace::{ModalView, Workspace, WorkspaceId, WorkspaceLocation, WORKSPACE_DB};
|
use workspace::{ModalView, Workspace, WorkspaceId, WorkspaceLocation, WORKSPACE_DB};
|
||||||
|
|
||||||
pub use projects::OpenRecent;
|
gpui::actions!(projects, [OpenRecent]);
|
||||||
|
|
||||||
pub fn init(cx: &mut AppContext) {
|
pub fn init(cx: &mut AppContext) {
|
||||||
cx.observe_new_views(RecentProjects::register).detach();
|
cx.observe_new_views(RecentProjects::register).detach();
|
||||||
|
@ -94,6 +93,7 @@ impl RecentProjects {
|
||||||
Ok(())
|
Ok(())
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn open_popover(workspace: WeakView<Workspace>, cx: &mut WindowContext<'_>) -> View<Self> {
|
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), 20., cx))
|
||||||
}
|
}
|
||||||
|
@ -147,7 +147,11 @@ impl PickerDelegate for RecentProjectsDelegate {
|
||||||
type ListItem = ListItem;
|
type ListItem = ListItem;
|
||||||
|
|
||||||
fn placeholder_text(&self) -> Arc<str> {
|
fn placeholder_text(&self) -> Arc<str> {
|
||||||
"Search recent projects...".into()
|
Arc::from(format!(
|
||||||
|
"`{:?}` reuses the window, `{:?}` opens in new",
|
||||||
|
menu::Confirm,
|
||||||
|
menu::SecondaryConfirm,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn match_count(&self) -> usize {
|
fn match_count(&self) -> usize {
|
||||||
|
@ -207,17 +211,26 @@ impl PickerDelegate for RecentProjectsDelegate {
|
||||||
Task::ready(())
|
Task::ready(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn confirm(&mut self, _: bool, cx: &mut ViewContext<Picker<Self>>) {
|
fn confirm(&mut self, secondary: bool, cx: &mut ViewContext<Picker<Self>>) {
|
||||||
if let Some((selected_match, workspace)) = self
|
if let Some((selected_match, workspace)) = self
|
||||||
.matches
|
.matches
|
||||||
.get(self.selected_index())
|
.get(self.selected_index())
|
||||||
.zip(self.workspace.upgrade())
|
.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
|
workspace
|
||||||
.update(cx, |workspace, cx| {
|
.update(cx, |workspace, cx| {
|
||||||
workspace
|
if workspace.database_id() != *candidate_workspace_id {
|
||||||
.open_workspace_for_paths(workspace_location.paths().as_ref().clone(), cx)
|
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);
|
.detach_and_log_err(cx);
|
||||||
cx.emit(DismissEvent);
|
cx.emit(DismissEvent);
|
||||||
|
|
|
@ -1387,7 +1387,9 @@ impl Workspace {
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(task) = this
|
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()
|
.log_err()
|
||||||
{
|
{
|
||||||
task.await.log_err();
|
task.await.log_err();
|
||||||
|
@ -1398,6 +1400,7 @@ impl Workspace {
|
||||||
|
|
||||||
pub fn open_workspace_for_paths(
|
pub fn open_workspace_for_paths(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
replace_current_window: bool,
|
||||||
paths: Vec<PathBuf>,
|
paths: Vec<PathBuf>,
|
||||||
cx: &mut ViewContext<Self>,
|
cx: &mut ViewContext<Self>,
|
||||||
) -> Task<Result<()>> {
|
) -> Task<Result<()>> {
|
||||||
|
@ -1405,7 +1408,10 @@ impl Workspace {
|
||||||
let is_remote = self.project.read(cx).is_remote();
|
let is_remote = self.project.read(cx).is_remote();
|
||||||
let has_worktree = self.project.read(cx).worktrees().next().is_some();
|
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 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
|
None
|
||||||
} else {
|
} else {
|
||||||
window
|
window
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue