feat: use async fd when using tokio (#4927)
* feat: use async fd when using tokio * whoops fix ios
This commit is contained in:
1 parent
75bb61ea67
commit
1236296ea6
3 files changed
+112
-7
No files matched your search
Generated
+1
-1
@@ -5839,7 +5839,7 @@ dependencies = [
|
||||
"getrandom 0.3.4",
|
||||
"http-range",
|
||||
"ouroboros",
|
||||
"pollster",
|
||||
"pollster 0.4.0",
|
||||
"rand 0.9.2",
|
||||
"reqwest 0.12.24",
|
||||
"separator",
|
||||
|
||||
@@ -54,6 +54,19 @@ impl FileDialogRequest {
|
||||
vec![]
|
||||
}
|
||||
|
||||
#[cfg(not(any(
|
||||
target_os = "windows",
|
||||
target_os = "macos",
|
||||
target_os = "linux",
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd"
|
||||
)))]
|
||||
pub(crate) async fn get_file_event_async(&self) -> Vec<PathBuf> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
#[cfg(any(
|
||||
target_os = "windows",
|
||||
target_os = "macos",
|
||||
@@ -63,9 +76,8 @@ impl FileDialogRequest {
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd"
|
||||
))]
|
||||
pub(crate) fn get_file_event(&self) -> Vec<PathBuf> {
|
||||
pub(crate) fn get_file_event_sync(&self) -> Vec<PathBuf> {
|
||||
let dialog = rfd::FileDialog::new();
|
||||
|
||||
if self.directory {
|
||||
self.get_file_event_for_folder(dialog)
|
||||
} else {
|
||||
@@ -73,6 +85,78 @@ impl FileDialogRequest {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(
|
||||
target_os = "windows",
|
||||
target_os = "macos",
|
||||
target_os = "linux",
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd"
|
||||
))]
|
||||
pub(crate) async fn get_file_event_async(&self) -> Vec<PathBuf> {
|
||||
let mut dialog = rfd::AsyncFileDialog::new();
|
||||
|
||||
if self.directory {
|
||||
if self.multiple {
|
||||
dialog
|
||||
.pick_folders()
|
||||
.await
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.map(|f| f.path().to_path_buf())
|
||||
.collect()
|
||||
} else {
|
||||
dialog
|
||||
.pick_folder()
|
||||
.await
|
||||
.into_iter()
|
||||
.map(|f| f.path().to_path_buf())
|
||||
.collect()
|
||||
}
|
||||
} else {
|
||||
let filters: Vec<_> = self
|
||||
.accept
|
||||
.as_deref()
|
||||
.unwrap_or(".*")
|
||||
.split(',')
|
||||
.filter_map(|s| Filters::from_str(s.trim()).ok())
|
||||
.collect();
|
||||
|
||||
let file_extensions: Vec<_> = filters
|
||||
.iter()
|
||||
.flat_map(|f| f.as_extensions().into_iter())
|
||||
.collect();
|
||||
|
||||
let filter_name = file_extensions
|
||||
.iter()
|
||||
.map(|extension| format!("*.{extension}"))
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ");
|
||||
|
||||
dialog = dialog.add_filter(filter_name, file_extensions.as_slice());
|
||||
|
||||
let files: Vec<_> = if self.multiple {
|
||||
dialog
|
||||
.pick_files()
|
||||
.await
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.map(|f| f.path().to_path_buf())
|
||||
.collect()
|
||||
} else {
|
||||
dialog
|
||||
.pick_file()
|
||||
.await
|
||||
.into_iter()
|
||||
.map(|f| f.path().to_path_buf())
|
||||
.collect()
|
||||
};
|
||||
|
||||
files
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(
|
||||
target_os = "windows",
|
||||
target_os = "macos",
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::path::PathBuf;
|
||||
|
||||
use crate::{assets::*, webview::WebviewEdits};
|
||||
use crate::{document::NATIVE_EVAL_JS, file_upload::FileDialogRequest};
|
||||
use base64::prelude::BASE64_STANDARD;
|
||||
@@ -63,9 +65,10 @@ pub(super) fn desktop_handler(
|
||||
|
||||
// If the request is asking for a file dialog, handle that, returning the list of files selected
|
||||
if trimmed_uri == "__file_dialog" {
|
||||
if let Err(err) = file_dialog_responder(request, responder) {
|
||||
if let Err(err) = file_dialog_responder_sync(request, responder) {
|
||||
tracing::error!("Failed to handle file dialog request: {err:?}");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -177,7 +180,7 @@ fn module_loader(root_id: &str, headless: bool, edit_state: &WebviewEdits) -> St
|
||||
)
|
||||
}
|
||||
|
||||
fn file_dialog_responder(
|
||||
fn file_dialog_responder_sync(
|
||||
request: wry::http::Request<Vec<u8>>,
|
||||
responder: wry::RequestAsyncResponder,
|
||||
) -> dioxus_core::Result<()> {
|
||||
@@ -191,11 +194,29 @@ fn file_dialog_responder(
|
||||
let data_from_header = base64::Engine::decode(&BASE64_STANDARD, header.as_bytes())
|
||||
.context("Failed to decode x-dioxus-data header from base64")?;
|
||||
|
||||
let mut file_dialog: FileDialogRequest = serde_json::from_slice(&data_from_header)
|
||||
let file_dialog: FileDialogRequest = serde_json::from_slice(&data_from_header)
|
||||
.context("Failed to parse x-dioxus-data header as JSON")?;
|
||||
|
||||
let file_list = file_dialog.get_file_event();
|
||||
#[cfg(feature = "tokio_runtime")]
|
||||
tokio::spawn(async move {
|
||||
let file_list = file_dialog.get_file_event_async().await;
|
||||
_ = respond_to_file_dialog(file_dialog, file_list, responder);
|
||||
});
|
||||
|
||||
#[cfg(not(feature = "tokio_runtime"))]
|
||||
{
|
||||
let file_list = file_dialog.get_file_event_sync();
|
||||
respond_to_file_dialog(file_dialog, file_list, responder)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn respond_to_file_dialog(
|
||||
mut file_dialog: FileDialogRequest,
|
||||
file_list: Vec<PathBuf>,
|
||||
responder: wry::RequestAsyncResponder,
|
||||
) -> dioxus_core::Result<()> {
|
||||
// Get the position of the entry we're updating, so we can insert new entries in the same place
|
||||
// If we can't find it, just append to the end. This is usually due to the input not being in a form element.
|
||||
let position_of_entry = file_dialog
|
||||
|
||||
Reference in new issue
Block a user