Merge pull request #1074 from kaid/directory-selection-dialog
Add directory support for file input.
This commit is contained in:
6 files changed
+68
-30
No files matched your search
+21
-6
@@ -1,32 +1,47 @@
|
|||||||
#![allow(non_snake_case)]
|
#![allow(non_snake_case)]
|
||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
|
use tokio::time::sleep;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
dioxus_desktop::launch(App);
|
dioxus_desktop::launch(App);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn App(cx: Scope) -> Element {
|
fn App(cx: Scope) -> Element {
|
||||||
|
let enable_directory_upload = use_state(cx, || false);
|
||||||
let files_uploaded: &UseRef<Vec<String>> = use_ref(cx, Vec::new);
|
let files_uploaded: &UseRef<Vec<String>> = use_ref(cx, Vec::new);
|
||||||
|
|
||||||
cx.render(rsx! {
|
cx.render(rsx! {
|
||||||
|
label {
|
||||||
|
input {
|
||||||
|
r#type: "checkbox",
|
||||||
|
checked: "{enable_directory_upload}",
|
||||||
|
oninput: move |evt| {
|
||||||
|
enable_directory_upload.set(evt.value.parse().unwrap());
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"Enable directory upload"
|
||||||
|
}
|
||||||
|
|
||||||
input {
|
input {
|
||||||
r#type: "file",
|
r#type: "file",
|
||||||
accept: ".txt, .rs",
|
accept: ".txt,.rs",
|
||||||
multiple: true,
|
multiple: true,
|
||||||
|
directory: **enable_directory_upload,
|
||||||
onchange: |evt| {
|
onchange: |evt| {
|
||||||
to_owned![files_uploaded];
|
to_owned![files_uploaded];
|
||||||
async move {
|
async move {
|
||||||
if let Some(file_engine) = &evt.files {
|
if let Some(file_engine) = &evt.files {
|
||||||
let files = file_engine.files();
|
let files = file_engine.files();
|
||||||
for file_name in &files {
|
for file_name in files {
|
||||||
if let Some(file) = file_engine.read_file_to_string(file_name).await{
|
sleep(std::time::Duration::from_secs(1)).await;
|
||||||
files_uploaded.write().push(file);
|
files_uploaded.write().push(file_name);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
|
|
||||||
|
div { "progress: {files_uploaded.read().len()}" },
|
||||||
|
|
||||||
ul {
|
ul {
|
||||||
for file in files_uploaded.read().iter() {
|
for file in files_uploaded.read().iter() {
|
||||||
|
|||||||
@@ -8,36 +8,24 @@ pub(crate) struct FileDialogRequest {
|
|||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
accept: Option<String>,
|
accept: Option<String>,
|
||||||
multiple: bool,
|
multiple: bool,
|
||||||
|
directory: bool,
|
||||||
pub event: String,
|
pub event: String,
|
||||||
pub target: usize,
|
pub target: usize,
|
||||||
pub bubbles: bool,
|
pub bubbles: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(any(
|
fn get_file_event_for_folder(request: &FileDialogRequest, dialog: rfd::FileDialog) -> Vec<PathBuf> {
|
||||||
target_os = "windows",
|
if request.multiple {
|
||||||
target_os = "macos",
|
dialog.pick_folders().into_iter().flatten().collect()
|
||||||
target_os = "linux",
|
} else {
|
||||||
target_os = "dragonfly",
|
dialog.pick_folder().into_iter().collect()
|
||||||
target_os = "freebsd",
|
}
|
||||||
target_os = "netbsd",
|
|
||||||
target_os = "openbsd"
|
|
||||||
)))]
|
|
||||||
pub(crate) fn get_file_event(_request: &FileDialogRequest) -> Vec<PathBuf> {
|
|
||||||
vec![]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(
|
fn get_file_event_for_file(
|
||||||
target_os = "windows",
|
request: &FileDialogRequest,
|
||||||
target_os = "macos",
|
mut dialog: rfd::FileDialog,
|
||||||
target_os = "linux",
|
) -> Vec<PathBuf> {
|
||||||
target_os = "dragonfly",
|
|
||||||
target_os = "freebsd",
|
|
||||||
target_os = "netbsd",
|
|
||||||
target_os = "openbsd"
|
|
||||||
))]
|
|
||||||
pub(crate) fn get_file_event(request: &FileDialogRequest) -> Vec<PathBuf> {
|
|
||||||
let mut dialog = rfd::FileDialog::new();
|
|
||||||
|
|
||||||
let filters: Vec<_> = request
|
let filters: Vec<_> = request
|
||||||
.accept
|
.accept
|
||||||
.as_deref()
|
.as_deref()
|
||||||
@@ -62,6 +50,38 @@ pub(crate) fn get_file_event(request: &FileDialogRequest) -> Vec<PathBuf> {
|
|||||||
files
|
files
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[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) fn get_file_event(_request: &FileDialogRequest) -> Vec<PathBuf> {
|
||||||
|
vec![]
|
||||||
|
}
|
||||||
|
|
||||||
|
#[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) fn get_file_event(request: &FileDialogRequest) -> Vec<PathBuf> {
|
||||||
|
let dialog = rfd::FileDialog::new();
|
||||||
|
|
||||||
|
if request.directory {
|
||||||
|
get_file_event_for_folder(request, dialog)
|
||||||
|
} else {
|
||||||
|
get_file_event_for_file(request, dialog)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
enum Filters {
|
enum Filters {
|
||||||
Extension(String),
|
Extension(String),
|
||||||
Mime(String),
|
Mime(String),
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ fn module_loader(root_name: &str) -> String {
|
|||||||
let target_id = find_real_id(target);
|
let target_id = find_real_id(target);
|
||||||
if (target_id !== null) {
|
if (target_id !== null) {
|
||||||
const send = (event_name) => {
|
const send = (event_name) => {
|
||||||
const message = serializeIpcMessage("file_diolog", { accept: target.getAttribute("accept"), multiple: target.hasAttribute("multiple"), target: parseInt(target_id), bubbles: event_bubbles(event_name), event: event_name });
|
const message = serializeIpcMessage("file_diolog", { accept: target.getAttribute("accept"), directory: target.getAttribute("webkitdirectory") === "true", multiple: target.hasAttribute("multiple"), target: parseInt(target_id), bubbles: event_bubbles(event_name), event: event_name });
|
||||||
window.ipc.postMessage(message);
|
window.ipc.postMessage(message);
|
||||||
};
|
};
|
||||||
send("change&input");
|
send("change&input");
|
||||||
|
|||||||
@@ -1098,6 +1098,7 @@ builder_constructors! {
|
|||||||
autofocus: Bool DEFAULT,
|
autofocus: Bool DEFAULT,
|
||||||
capture: String DEFAULT,
|
capture: String DEFAULT,
|
||||||
checked: Bool DEFAULT,
|
checked: Bool DEFAULT,
|
||||||
|
directory: Bool "webkitdirectory",
|
||||||
disabled: Bool DEFAULT,
|
disabled: Bool DEFAULT,
|
||||||
form: Id DEFAULT,
|
form: Id DEFAULT,
|
||||||
formaction: Uri DEFAULT,
|
formaction: Uri DEFAULT,
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ const bool_attrs = {
|
|||||||
reversed: true,
|
reversed: true,
|
||||||
selected: true,
|
selected: true,
|
||||||
truespeed: true,
|
truespeed: true,
|
||||||
|
webkitdirectory: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
export function setAttributeInner(node, field, value, ns) {
|
export function setAttributeInner(node, field, value, ns) {
|
||||||
|
|||||||
@@ -163,6 +163,7 @@ mod js {
|
|||||||
reversed: true,
|
reversed: true,
|
||||||
selected: true,
|
selected: true,
|
||||||
truespeed: true,
|
truespeed: true,
|
||||||
|
webkitdirectory: true,
|
||||||
};
|
};
|
||||||
function truthy(val) {
|
function truthy(val) {
|
||||||
return val === "true" || val === true;
|
return val === "true" || val === true;
|
||||||
|
|||||||
Reference in new issue
Block a user