Open configured vault folders
This commit is contained in:
69
apps/desktop/src/folder_picker.rs
Normal file
69
apps/desktop/src/folder_picker.rs
Normal file
@@ -0,0 +1,69 @@
|
||||
//! Platform folder pickers without helper processes.
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[cfg(any(target_os = "macos", target_os = "windows"))]
|
||||
pub async fn pick_folder(initial: Option<PathBuf>) -> Result<Option<PathBuf>, String> {
|
||||
let mut dialog = rfd::AsyncFileDialog::new().set_title("Open Password Store");
|
||||
if let Some(initial) = initial.filter(|path| path.is_dir()) {
|
||||
dialog = dialog.set_directory(initial);
|
||||
}
|
||||
Ok(dialog
|
||||
.pick_folder()
|
||||
.await
|
||||
.map(|folder| folder.path().to_owned()))
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
pub async fn pick_folder(initial: Option<PathBuf>) -> Result<Option<PathBuf>, String> {
|
||||
use ashpd::{
|
||||
PortalError,
|
||||
desktop::{file_chooser::SelectedFiles, request::ResponseError},
|
||||
};
|
||||
|
||||
let mut request = SelectedFiles::open_file()
|
||||
.title("Open Password Store")
|
||||
.accept_label("Open")
|
||||
.modal(true)
|
||||
.multiple(false)
|
||||
.directory(true);
|
||||
if let Some(initial) = initial.filter(|path| path.is_dir()) {
|
||||
request = request
|
||||
.current_folder(initial)
|
||||
.map_err(|error| error.to_string())?;
|
||||
}
|
||||
let response = request.send().await.and_then(|request| request.response());
|
||||
let selected = match response {
|
||||
Ok(selected) => selected,
|
||||
Err(ashpd::Error::Response(ResponseError::Cancelled))
|
||||
| Err(ashpd::Error::Portal(PortalError::Cancelled(_))) => return Ok(None),
|
||||
Err(error) => return Err(error.to_string()),
|
||||
};
|
||||
selected
|
||||
.uris()
|
||||
.first()
|
||||
.ok_or_else(|| "folder portal returned no selection".to_owned())
|
||||
.and_then(|uri| file_uri_path(uri.as_str()))
|
||||
.map(Some)
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
fn file_uri_path(uri: &str) -> Result<PathBuf, String> {
|
||||
let uri = url::Url::parse(uri).map_err(|_| "folder portal returned an invalid URI")?;
|
||||
uri.to_file_path()
|
||||
.map_err(|()| "folder portal returned a non-file URI".to_owned())
|
||||
}
|
||||
|
||||
#[cfg(all(test, target_os = "linux"))]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn portal_file_uris_are_decoded_and_other_schemes_are_rejected() {
|
||||
assert_eq!(
|
||||
file_uri_path("file:///tmp/password%20store").expect("file URI"),
|
||||
PathBuf::from("/tmp/password store")
|
||||
);
|
||||
assert!(file_uri_path("https://example.test/store").is_err());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user