zed: Fix no way to open local folder from remote window (#30954)
Closes #27642 Currently, the `Open (cmd-o)` action is used to open a local folder picker when in a local project, and Zed's remote path modal in the case of a remote project. While this looks intentional, there is now no way to open a local project when you are in a remote project window. Neither by shortcut, nor by UI, as the "Open Local Folder" button uses the same `Open` action. The reverse is not true, as we already have an `Open Remote (ctrl-cmd-o)` action to open the remote modal, where you can select "Add Folder" which opens the same Zed's remote path modal. This already works in both local and remote window cases. This PR makes two changes: 1. It changes `Open (cmd-o)` action such that it should always open the local file picker regardless of which project is currently open, local or remote. This way we have two non-ambiguios actions `Open` and `Open Remote`. 2. It also changes the "Open a project" button (which shows up when no project is open in the project panel) to open the recent modal (which contains buttons to open either local or remote) instead of choosing on behalf of the user. P.S. If we want to open Zed's remote path modal directly, it should be different action altogether. Not covered for now. Release Notes: - Fixed issue where "Open local folder" was not opening folder picker when connected to a remote host. - Added `from_existing_connection` flag to `OpenRemote` action to directly open path picker for current connection, bypassing the Remote Projects modal.
This commit is contained in:
parent
851121ffd4
commit
c7aae6bd62
9 changed files with 91 additions and 16 deletions
|
@ -512,6 +512,8 @@
|
|||
"alt-ctrl-o": "projects::OpenRecent",
|
||||
"alt-shift-open": "projects::OpenRemote",
|
||||
"alt-ctrl-shift-o": "projects::OpenRemote",
|
||||
// Change to open path modal for existing remote connection by setting the parameter
|
||||
// "alt-ctrl-shift-o": "["projects::OpenRemote", { "from_existing_connection": true }]",
|
||||
"alt-ctrl-shift-b": "branches::OpenRecent",
|
||||
"alt-shift-enter": "toast::RunAction",
|
||||
"ctrl-~": "workspace::NewTerminal",
|
||||
|
|
|
@ -588,6 +588,7 @@
|
|||
// "alt-cmd-o": ["projects::OpenRecent", {"create_new_window": true }],
|
||||
"alt-cmd-o": "projects::OpenRecent",
|
||||
"ctrl-cmd-o": "projects::OpenRemote",
|
||||
"ctrl-cmd-shift-o": ["projects::OpenRemote", { "from_existing_connection": true }],
|
||||
"alt-cmd-b": "branches::OpenRecent",
|
||||
"ctrl-~": "workspace::NewTerminal",
|
||||
"cmd-s": "workspace::Save",
|
||||
|
|
|
@ -65,6 +65,7 @@ use workspace::{
|
|||
notifications::{DetachAndPromptErr, NotifyTaskExt},
|
||||
};
|
||||
use worktree::CreatedEntry;
|
||||
use zed_actions::OpenRecent;
|
||||
|
||||
const PROJECT_PANEL_KEY: &str = "ProjectPanel";
|
||||
const NEW_ENTRY_ID: ProjectEntryId = ProjectEntryId::MAX;
|
||||
|
@ -4881,11 +4882,16 @@ impl Render for ProjectPanel {
|
|||
.child(
|
||||
Button::new("open_project", "Open a project")
|
||||
.full_width()
|
||||
.key_binding(KeyBinding::for_action(&workspace::Open, window, cx))
|
||||
.key_binding(KeyBinding::for_action_in(
|
||||
&OpenRecent::default(),
|
||||
&self.focus_handle,
|
||||
window,
|
||||
cx,
|
||||
))
|
||||
.on_click(cx.listener(|this, _, window, cx| {
|
||||
this.workspace
|
||||
.update(cx, |_, cx| {
|
||||
window.dispatch_action(Box::new(workspace::Open), cx)
|
||||
window.dispatch_action(OpenRecent::default().boxed_clone(), cx);
|
||||
})
|
||||
.log_err();
|
||||
})),
|
||||
|
|
|
@ -468,9 +468,21 @@ impl PickerDelegate for RecentProjectsDelegate {
|
|||
.border_color(cx.theme().colors().border_variant)
|
||||
.child(
|
||||
Button::new("remote", "Open Remote Folder")
|
||||
.key_binding(KeyBinding::for_action(&OpenRemote, window, cx))
|
||||
.key_binding(KeyBinding::for_action(
|
||||
&OpenRemote {
|
||||
from_existing_connection: false,
|
||||
},
|
||||
window,
|
||||
cx,
|
||||
))
|
||||
.on_click(|_, window, cx| {
|
||||
window.dispatch_action(OpenRemote.boxed_clone(), cx)
|
||||
window.dispatch_action(
|
||||
OpenRemote {
|
||||
from_existing_connection: false,
|
||||
}
|
||||
.boxed_clone(),
|
||||
cx,
|
||||
)
|
||||
}),
|
||||
)
|
||||
.child(
|
||||
|
|
|
@ -350,7 +350,11 @@ impl RemoteServerProjects {
|
|||
_window: Option<&mut Window>,
|
||||
_: &mut Context<Workspace>,
|
||||
) {
|
||||
workspace.register_action(|workspace, _: &OpenRemote, window, cx| {
|
||||
workspace.register_action(|workspace, action: &OpenRemote, window, cx| {
|
||||
if action.from_existing_connection {
|
||||
cx.propagate();
|
||||
return;
|
||||
}
|
||||
let handle = cx.entity().downgrade();
|
||||
let fs = workspace.project().read(cx).fs().clone();
|
||||
workspace.toggle_modal(window, cx, |window, cx| Self::new(fs, window, cx, handle))
|
||||
|
|
|
@ -432,14 +432,22 @@ impl TitleBar {
|
|||
.tooltip(move |window, cx| {
|
||||
Tooltip::with_meta(
|
||||
"Remote Project",
|
||||
Some(&OpenRemote),
|
||||
Some(&OpenRemote {
|
||||
from_existing_connection: false,
|
||||
}),
|
||||
meta.clone(),
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
})
|
||||
.on_click(|_, window, cx| {
|
||||
window.dispatch_action(OpenRemote.boxed_clone(), cx);
|
||||
window.dispatch_action(
|
||||
OpenRemote {
|
||||
from_existing_connection: false,
|
||||
}
|
||||
.boxed_clone(),
|
||||
cx,
|
||||
);
|
||||
})
|
||||
.into_any_element(),
|
||||
)
|
||||
|
|
|
@ -503,7 +503,7 @@ fn register_actions(
|
|||
directories: true,
|
||||
multiple: true,
|
||||
},
|
||||
DirectoryLister::Project(workspace.project().clone()),
|
||||
DirectoryLister::Local(workspace.app_state().fs.clone()),
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
|
@ -515,11 +515,42 @@ fn register_actions(
|
|||
|
||||
if let Some(task) = this
|
||||
.update_in(cx, |this, window, cx| {
|
||||
if this.project().read(cx).is_local() {
|
||||
this.open_workspace_for_paths(false, paths, window, cx)
|
||||
} else {
|
||||
open_new_ssh_project_from_project(this, paths, window, cx)
|
||||
}
|
||||
this.open_workspace_for_paths(false, paths, window, cx)
|
||||
})
|
||||
.log_err()
|
||||
{
|
||||
task.await.log_err();
|
||||
}
|
||||
})
|
||||
.detach()
|
||||
})
|
||||
.register_action(|workspace, action: &zed_actions::OpenRemote, window, cx| {
|
||||
if !action.from_existing_connection {
|
||||
cx.propagate();
|
||||
return;
|
||||
}
|
||||
// You need existing remote connection to open it this way
|
||||
if workspace.project().read(cx).is_local() {
|
||||
return;
|
||||
}
|
||||
telemetry::event!("Project Opened");
|
||||
let paths = workspace.prompt_for_open_path(
|
||||
PathPromptOptions {
|
||||
files: true,
|
||||
directories: true,
|
||||
multiple: true,
|
||||
},
|
||||
DirectoryLister::Project(workspace.project().clone()),
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
cx.spawn_in(window, async move |this, cx| {
|
||||
let Some(paths) = paths.await.log_err().flatten() else {
|
||||
return;
|
||||
};
|
||||
if let Some(task) = this
|
||||
.update_in(cx, |this, window, cx| {
|
||||
open_new_ssh_project_from_project(this, paths, window, cx)
|
||||
})
|
||||
.log_err()
|
||||
{
|
||||
|
|
|
@ -70,7 +70,12 @@ pub fn app_menus() -> Vec<Menu> {
|
|||
create_new_window: true,
|
||||
},
|
||||
),
|
||||
MenuItem::action("Open Remote...", zed_actions::OpenRemote),
|
||||
MenuItem::action(
|
||||
"Open Remote...",
|
||||
zed_actions::OpenRemote {
|
||||
from_existing_connection: false,
|
||||
},
|
||||
),
|
||||
MenuItem::separator(),
|
||||
MenuItem::action("Add Folder to Project…", workspace::AddFolderToProject),
|
||||
MenuItem::separator(),
|
||||
|
|
|
@ -243,8 +243,14 @@ pub struct OpenRecent {
|
|||
pub create_new_window: bool,
|
||||
}
|
||||
|
||||
impl_actions!(projects, [OpenRecent]);
|
||||
actions!(projects, [OpenRemote]);
|
||||
#[derive(PartialEq, Clone, Deserialize, Default, JsonSchema)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct OpenRemote {
|
||||
#[serde(default)]
|
||||
pub from_existing_connection: bool,
|
||||
}
|
||||
|
||||
impl_actions!(projects, [OpenRecent, OpenRemote]);
|
||||
|
||||
/// Where to spawn the task in the UI.
|
||||
#[derive(Default, Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue