Add ability to open files with system default application (#17231)

This commit is contained in:
KorigamiK 2024-09-11 00:06:36 +05:30 committed by GitHub
parent 06142f975b
commit ae3880e71a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 63 additions and 1 deletions

View file

@ -553,6 +553,7 @@
"ctrl-backspace": ["project_panel::Delete", { "skip_prompt": false }],
"ctrl-delete": ["project_panel::Delete", { "skip_prompt": false }],
"alt-ctrl-r": "project_panel::RevealInFileManager",
"ctrl-shift-enter": "project_panel::OpenWithSystem",
"alt-shift-f": "project_panel::NewSearchInDirectory",
"shift-down": "menu::SelectNext",
"shift-up": "menu::SelectPrev",

View file

@ -563,8 +563,8 @@
"cmd-backspace": ["project_panel::Trash", { "skip_prompt": true }],
"cmd-delete": ["project_panel::Delete", { "skip_prompt": false }],
"alt-cmd-r": "project_panel::RevealInFileManager",
"ctrl-shift-enter": "project_panel::OpenWithSystem",
"cmd-alt-backspace": ["project_panel::Delete", { "skip_prompt": false }],
"alt-shift-f": "project_panel::NewSearchInDirectory",
"shift-down": "menu::SelectNext",
"shift-up": "menu::SelectPrev",

View file

@ -493,6 +493,7 @@
"v": "project_panel::OpenPermanent",
"p": "project_panel::Open",
"x": "project_panel::RevealInFileManager",
"s": "project_panel::OpenWithSystem",
"shift-g": "menu::SelectLast",
"g g": "menu::SelectFirst",
"-": "project_panel::SelectParent",

View file

@ -657,6 +657,11 @@ impl AppContext {
self.platform.reveal_path(path)
}
/// Opens the specified path with the system's default application.
pub fn open_with_system(&self, path: &Path) {
self.platform.open_with_system(path)
}
/// Returns whether the user has configured scrollbars to auto-hide at the platform level.
pub fn should_auto_hide_scrollbars(&self) -> bool {
self.platform.should_auto_hide_scrollbars()

View file

@ -149,6 +149,7 @@ pub(crate) trait Platform: 'static {
) -> oneshot::Receiver<Result<Option<Vec<PathBuf>>>>;
fn prompt_for_new_path(&self, directory: &Path) -> oneshot::Receiver<Result<Option<PathBuf>>>;
fn reveal_path(&self, path: &Path);
fn open_with_system(&self, path: &Path);
fn on_quit(&self, callback: Box<dyn FnMut()>);
fn on_reopen(&self, callback: Box<dyn FnMut()>);

View file

@ -351,6 +351,19 @@ impl<P: LinuxClient + 'static> Platform for P {
self.reveal_path(path.to_owned());
}
fn open_with_system(&self, path: &Path) {
let executor = self.background_executor().clone();
let path = path.to_owned();
executor
.spawn(async move {
let _ = std::process::Command::new("xdg-open")
.arg(path)
.spawn()
.expect("Failed to open file with xdg-open");
})
.detach();
}
fn on_quit(&self, callback: Box<dyn FnMut()>) {
self.with_common(|common| {
common.callbacks.quit = Some(callback);

View file

@ -718,6 +718,20 @@ impl Platform for MacPlatform {
}
}
fn open_with_system(&self, path: &Path) {
let path = path.to_path_buf();
self.0
.lock()
.background_executor
.spawn(async move {
std::process::Command::new("open")
.arg(path)
.spawn()
.expect("Failed to open file");
})
.detach();
}
fn on_quit(&self, callback: Box<dyn FnMut()>) {
self.0.lock().quit = Some(callback);
}

View file

@ -318,6 +318,10 @@ impl Platform for TestPlatform {
fn register_url_scheme(&self, _: &str) -> Task<anyhow::Result<()>> {
unimplemented!()
}
fn open_with_system(&self, _path: &Path) {
unimplemented!()
}
}
#[cfg(target_os = "windows")]

View file

@ -400,6 +400,19 @@ impl Platform for WindowsPlatform {
.detach();
}
fn open_with_system(&self, path: &Path) {
let executor = self.background_executor().clone();
let path = path.to_owned();
executor
.spawn(async move {
let _ = std::process::Command::new("cmd")
.args(&["/c", "start", "", path.to_str().expect("path to string")])
.spawn()
.expect("Failed to open file");
})
.detach();
}
fn on_quit(&self, callback: Box<dyn FnMut()>) {
self.state.borrow_mut().callbacks.quit = Some(callback);
}

View file

@ -146,6 +146,7 @@ actions!(
CopyRelativePath,
Duplicate,
RevealInFileManager,
OpenWithSystem,
Cut,
Paste,
Rename,
@ -500,6 +501,7 @@ impl ProjectPanel {
.when(cfg!(not(target_os = "macos")), |menu| {
menu.action("Reveal in File Manager", Box::new(RevealInFileManager))
})
.action("Open in Default App", Box::new(OpenWithSystem))
.action("Open in Terminal", Box::new(OpenInTerminal))
.when(is_dir, |menu| {
menu.separator()
@ -1497,6 +1499,13 @@ impl ProjectPanel {
}
}
fn open_system(&mut self, _: &OpenWithSystem, cx: &mut ViewContext<Self>) {
if let Some((worktree, entry)) = self.selected_entry(cx) {
let abs_path = worktree.abs_path().join(&entry.path);
cx.open_with_system(&abs_path);
}
}
fn open_in_terminal(&mut self, _: &OpenInTerminal, cx: &mut ViewContext<Self>) {
if let Some((worktree, entry)) = self.selected_sub_entry(cx) {
let abs_path = worktree.abs_path().join(&entry.path);
@ -2711,6 +2720,7 @@ impl Render for ProjectPanel {
})
.when(project.is_local_or_ssh(), |el| {
el.on_action(cx.listener(Self::reveal_in_finder))
.on_action(cx.listener(Self::open_system))
.on_action(cx.listener(Self::open_in_terminal))
})
.on_mouse_down(