Add additive KDBX importer
This commit is contained in:
@@ -32,6 +32,30 @@ pub async fn pick_qr_image() -> Result<Option<SecretBytes>, String> {
|
||||
.transpose()
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "macos", target_os = "windows"))]
|
||||
pub async fn pick_kdbx_file() -> Result<Option<PathBuf>, String> {
|
||||
pick_file("Import KeePass Database", "KeePass database", &["kdbx"]).await
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "macos", target_os = "windows"))]
|
||||
pub async fn pick_key_file() -> Result<Option<PathBuf>, String> {
|
||||
pick_file("Select KeePass Key File", "Key file", &["key", "keyx"]).await
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "macos", target_os = "windows"))]
|
||||
async fn pick_file(
|
||||
title: &str,
|
||||
filter_name: &str,
|
||||
extensions: &[&str],
|
||||
) -> Result<Option<PathBuf>, String> {
|
||||
Ok(rfd::AsyncFileDialog::new()
|
||||
.set_title(title)
|
||||
.add_filter(filter_name, extensions)
|
||||
.pick_file()
|
||||
.await
|
||||
.map(|file| file.path().to_owned()))
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
pub async fn pick_folder(initial: Option<PathBuf>) -> Result<Option<PathBuf>, String> {
|
||||
use ashpd::{
|
||||
@@ -96,6 +120,45 @@ pub async fn pick_qr_image() -> Result<Option<SecretBytes>, String> {
|
||||
.map_err(|error| error.to_string())
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
pub async fn pick_kdbx_file() -> Result<Option<PathBuf>, String> {
|
||||
pick_file("Import KeePass Database", "Import").await
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
pub async fn pick_key_file() -> Result<Option<PathBuf>, String> {
|
||||
pick_file("Select KeePass Key File", "Select").await
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
async fn pick_file(title: &str, accept_label: &str) -> Result<Option<PathBuf>, String> {
|
||||
use ashpd::{
|
||||
PortalError,
|
||||
desktop::{file_chooser::SelectedFiles, request::ResponseError},
|
||||
};
|
||||
|
||||
let response = SelectedFiles::open_file()
|
||||
.title(title)
|
||||
.accept_label(accept_label)
|
||||
.modal(true)
|
||||
.multiple(false)
|
||||
.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(|| "file 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")?;
|
||||
|
||||
Reference in New Issue
Block a user