use crate::error::PlatformError;
use crate::traits::file::{
ChooseDirectoryRequest, ChooseFileRequest, FileDialogFilter, FileDialogResult,
};
pub async fn choose_file_desktop(
request: ChooseFileRequest,
) -> Result<FileDialogResult, PlatformError> {
let dialog = apply_filters(
apply_common_options(
rfd::AsyncFileDialog::new(),
&request.title,
&request.default_path,
),
&request.filters,
);
if request.multiple {
match dialog.pick_files().await {
Some(handles) => Ok(FileDialogResult {
canceled: false,
paths: handles
.iter()
.map(|handle| handle.path().to_string_lossy().into_owned())
.collect(),
}),
None => Ok(canceled()),
}
} else {
match dialog.pick_file().await {
Some(handle) => Ok(FileDialogResult {
canceled: false,
paths: vec![handle.path().to_string_lossy().into_owned()],
}),
None => Ok(canceled()),
}
}
}
pub async fn choose_directory_desktop(
request: ChooseDirectoryRequest,
) -> Result<FileDialogResult, PlatformError> {
let dialog = apply_common_options(
rfd::AsyncFileDialog::new(),
&request.title,
&request.default_path,
);
match dialog.pick_folder().await {
Some(handle) => Ok(FileDialogResult {
canceled: false,
paths: vec![handle.path().to_string_lossy().into_owned()],
}),
None => Ok(canceled()),
}
}
fn canceled() -> FileDialogResult {
FileDialogResult {
canceled: true,
paths: vec![],
}
}
fn apply_common_options(
mut dialog: rfd::AsyncFileDialog,
title: &Option<String>,
default_path: &Option<String>,
) -> rfd::AsyncFileDialog {
if let Some(value) = title {
dialog = dialog.set_title(value);
}
if let Some(value) = default_path {
dialog = dialog.set_directory(value);
}
dialog
}
fn apply_filters(
mut dialog: rfd::AsyncFileDialog,
filters: &[FileDialogFilter],
) -> rfd::AsyncFileDialog {
for filter in filters {
if filter.extensions.is_empty() {
continue;
}
let name = filter.name.as_deref().unwrap_or("Files");
let exts: Vec<&str> = filter.extensions.iter().map(String::as_str).collect();
dialog = dialog.add_filter(name, &exts);
}
dialog
}