feat: use async fd when using tokio (#4927)

* feat: use async fd when using tokio

* whoops fix ios
This commit is contained in:
Jonathan Kelley authored and GitHub committed 2025-11-06 14:55:59 -03:00
1 parent 75bb61ea67
commit 1236296ea6
3 files changed
+112 -7

No files matched your search

Generated
+1 -1
View File
@@ -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",
+86 -2
View File
@@ -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",
+25 -4
View File
@@ -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