diff --git a/Cargo.lock b/Cargo.lock index 2240faaf..ef81c04c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6596,6 +6596,7 @@ dependencies = [ "url", "urlpattern", "windows 0.54.0", + "zbus", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index d011d0ab..4b075df4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,6 +23,7 @@ dunce = "1" specta = "=2.0.0-rc.20" glob = "0.3" urlpattern = "0.3" +zbus = "4" #tauri-specta = "=2.0.0-rc.11" [workspace.package] diff --git a/plugins/opener/Cargo.toml b/plugins/opener/Cargo.toml index bb3ecfab..0045fb95 100644 --- a/plugins/opener/Cargo.toml +++ b/plugins/opener/Cargo.toml @@ -51,3 +51,6 @@ features = [ "Win32_System_Com", "Win32_System_Registry", ] + +[target."cfg(any(target_os = \"linux\", target_os = \"dragonfly\", target_os = \"freebsd\", target_os = \"netbsd\", target_os = \"openbsd\"))".dependencies] +zbus = { workspace = true } diff --git a/plugins/opener/src/error.rs b/plugins/opener/src/error.rs index 50676df6..2f9dff4b 100644 --- a/plugins/opener/src/error.rs +++ b/plugins/opener/src/error.rs @@ -7,6 +7,7 @@ use std::path::PathBuf; use serde::{Serialize, Serializer}; #[derive(Debug, thiserror::Error)] +#[non_exhaustive] pub enum Error { #[cfg(mobile)] #[error(transparent)] @@ -21,15 +22,24 @@ pub enum Error { UnknownProgramName(String), #[error("Not allowed to open {0}")] NotAllowed(String), - /// API not supported on the current platform #[error("API not supported on the current platform")] UnsupportedPlatform, #[error(transparent)] #[cfg(windows)] Win32Error(#[from] windows::core::Error), - /// Path doesn't have a parent. #[error("Path doesn't have a parent: {0}")] NoParent(PathBuf), + #[error("Failed to convert path to file:// url")] + FailedToConvertPathToFileUrl, + #[error(transparent)] + #[cfg(any( + target_os = "linux", + target_os = "dragonfly", + target_os = "freebsd", + target_os = "netbsd", + target_os = "openbsd" + ))] + Zbus(#[from] zbus::Error), } impl Serialize for Error { diff --git a/plugins/opener/src/lib.rs b/plugins/opener/src/lib.rs index 5a40ec7e..48936874 100644 --- a/plugins/opener/src/lib.rs +++ b/plugins/opener/src/lib.rs @@ -19,15 +19,15 @@ tauri::ios_plugin_binding!(init_plugin_opener); mod commands; mod error; mod open; +mod reveal_item_in_dir; mod scope; mod scope_entry; -mod show_item_in_dir; pub use error::Error; type Result = std::result::Result; pub use open::{open, Program}; -pub use show_item_in_dir::show_item_in_dir; +pub use reveal_item_in_dir::reveal_item_in_dir; pub struct Opener { #[allow(dead_code)] @@ -51,8 +51,8 @@ impl Opener { .map_err(Into::into) } - pub fn show_item_in_dir>(&self, p: P) -> Result<()> { - show_item_in_dir::show_item_in_dir(p) + pub fn reveal_item_in_dir>(&self, p: P) -> Result<()> { + reveal_item_in_dir::reveal_item_in_dir(p) } } diff --git a/plugins/opener/src/show_item_in_dir.rs b/plugins/opener/src/reveal_item_in_dir.rs similarity index 56% rename from plugins/opener/src/show_item_in_dir.rs rename to plugins/opener/src/reveal_item_in_dir.rs index 96719120..5b3cc5bc 100644 --- a/plugins/opener/src/show_item_in_dir.rs +++ b/plugins/opener/src/reveal_item_in_dir.rs @@ -1,13 +1,12 @@ use std::path::Path; -use std::path::PathBuf; /// Show /// /// ## Platform-specific: /// /// - **Android / iOS:** Unsupported. -pub fn show_item_in_dir>(p: P) -> crate::Result<()> { - let p = p.as_ref().canonicalize()?; +pub fn reveal_item_in_dir>(path: P) -> crate::Result<()> { + let path = path.as_ref().canonicalize()?; #[cfg(any( windows, @@ -18,7 +17,7 @@ pub fn show_item_in_dir>(p: P) -> crate::Result<()> { target_os = "netbsd", target_os = "openbsd" ))] - return imp::show_item_in_dir(p); + return imp::reveal_item_in_dir(&path); #[cfg(not(any( windows, @@ -51,8 +50,8 @@ mod imp { }, }; - pub fn show_item_in_dir(p: PathBuf) -> crate::Result<()> { - let file = dunce::simplified(&p); + pub fn reveal_item_in_dir(path: &Path) -> crate::Result<()> { + let file = dunce::simplified(path); let _ = unsafe { CoInitialize(None) }; @@ -105,10 +104,63 @@ mod imp { target_os = "openbsd" ))] mod imp { + + use std::collections::HashMap; + use super::*; - pub fn show_item_in_dir(p: PathBuf) -> crate::Result<()> { - Ok(()) + pub fn reveal_item_in_dir(path: &Path) -> crate::Result<()> { + let connection = zbus::blocking::Connection::session()?; + + reveal_with_filemanager1(path, &connection) + .or_else(|_| reveal_with_open_uri_portal(path, &connection)) + } + + fn reveal_with_filemanager1( + path: &Path, + connection: &zbus::blocking::Connection, + ) -> crate::Result<()> { + let uri = url::Url::from_file_path(path) + .map_err(|_| crate::Error::FailedToConvertPathToFileUrl)?; + + #[zbus::proxy( + interface = "org.freedesktop.FileManager1", + default_service = "org.freedesktop.FileManager1", + default_path = "/org/freedesktop/FileManager1" + )] + trait FileManager1 { + async fn ShowItems(&self, name: Vec<&str>, arg2: &str) -> crate::Result<()>; + } + + let proxy = FileManager1ProxyBlocking::new(connection)?; + + proxy.ShowItems(vec![uri.as_str()], "") + } + + fn reveal_with_open_uri_portal( + path: &Path, + connection: &zbus::blocking::Connection, + ) -> crate::Result<()> { + let uri = url::Url::from_file_path(path) + .map_err(|_| crate::Error::FailedToConvertPathToFileUrl)?; + + #[zbus::proxy( + interface = "org.freedesktop.portal.Desktop", + default_service = "org.freedesktop.portal.OpenURI", + default_path = "/org/freedesktop/portal/desktop" + )] + trait PortalDesktop { + async fn OpenDirectory( + &self, + arg1: &str, + name: &str, + arg3: HashMap<&str, &str>, + ) -> crate::Result<()>; + } + + let proxy = PortalDesktopProxyBlocking::new(connection)?; + + proxy.OpenDirectory("", uri.as_str(), HashMap::new()) } } @@ -116,5 +168,5 @@ mod imp { mod imp { use super::*; - pub fn show_item_in_dir(p: PathBuf) -> crate::Result<()> {} + pub fn reveal_item_in_dir(path: &Path) -> crate::Result<()> {} } diff --git a/plugins/single-instance/Cargo.toml b/plugins/single-instance/Cargo.toml index 666c0d04..c5904839 100644 --- a/plugins/single-instance/Cargo.toml +++ b/plugins/single-instance/Cargo.toml @@ -42,7 +42,7 @@ features = [ ] [target."cfg(target_os = \"linux\")".dependencies] -zbus = "4" +zbus = { workspace = true } [features] semver = ["dep:semver"]