use crate::fs::get_absolute_path;
use crate::open::{Error, Result as OpenResult, Url};
use std::ffi::{OsStr, OsString};
use std::path::Path;
use std::process::Command;
use zbus::{blocking::Connection, proxy, Result};
#[proxy(
default_service = "org.freedesktop.FileManager1",
interface = "org.freedesktop.FileManager1",
default_path = "/org/freedesktop/FileManager1"
)]
trait FileManager {
fn show_folders(&self, uris: &[&str], startup_id: &str) -> Result<()>;
fn show_items(&self, uris: &[&str], startup_id: &str) -> Result<()>;
}
fn attempt_dbus_call(urls: &[&str], show_items: bool) -> OpenResult {
let con =
Connection::session().map_err(|e| Error::Other(format!("DBus connection error: {}", e)))?;
let proxy = FileManagerProxyBlocking::new(&con)
.map_err(|e| Error::Other(format!("DBus error: {}", e)))?;
let res = match show_items {
true => proxy.show_items(urls, "test"),
false => proxy.show_folders(urls, "test"),
};
match res {
Err(e) => Err(Error::Other(format!("DBus error: {}", e)))?,
Ok(_) => Ok(()),
}
}
fn attempt_xdg_open(url: &OsStr) -> OpenResult {
let res = Command::new("xdg-open").args([url]).spawn();
match res {
Ok(_) => Ok(()),
Err(e) => match e.kind() {
std::io::ErrorKind::NotFound => Err(Error::Unsupported),
_ => Err(Error::Io(e)),
},
}
}
pub fn open(url: &Url) -> OpenResult {
let path = Path::new(url.path());
let uri = url.to_os_str().map_err(Error::Io)?;
if !url.is_path() || !path.is_dir() {
return attempt_xdg_open(&uri);
}
match uri.to_str() {
Some(v) => attempt_dbus_call(&[v], false),
None => attempt_xdg_open(&uri),
}
}
pub fn show_in_files<'a, I: Iterator<Item = &'a Path>>(iter: I) -> OpenResult {
let v: std::io::Result<Vec<OsString>> = iter
.map(|v| {
get_absolute_path(v).map(|v| {
let mut s = OsString::with_capacity(v.as_os_str().len() + 7);
s.push("file://");
s.push(v.as_os_str());
s
})
})
.collect();
let paths = v.map_err(Error::Io)?;
let paths: Option<Vec<&str>> = paths.iter().map(|v| v.as_os_str().to_str()).collect();
match paths {
Some(v) => attempt_dbus_call(&v, true),
None => Err(Error::Other(
"one ore more paths contains invalid UTF-8 characters".into(),
)),
}
}