Merge branch 'upstream' into fix-links-liveview

This commit is contained in:
Evan Almloff committed 2023-04-26 17:56:13 -05:00
commit 7e292cc2fa
18 files changed
+628 -84

No files matched your search

+74
View File
@@ -0,0 +1,74 @@
use std::{path::PathBuf, str::FromStr};
use serde::Deserialize;
#[derive(Debug, Deserialize)]
pub(crate) struct FileDiologRequest {
accept: String,
multiple: bool,
pub event: String,
pub target: usize,
pub bubbles: bool,
}
pub(crate) fn get_file_event(request: &FileDiologRequest) -> Vec<PathBuf> {
let mut dialog = rfd::FileDialog::new();
let filters: Vec<_> = request
.accept
.split(',')
.filter_map(|s| Filters::from_str(s).ok())
.collect();
let file_extensions: Vec<_> = filters
.iter()
.flat_map(|f| f.as_extensions().into_iter())
.collect();
dialog = dialog.add_filter("name", file_extensions.as_slice());
let files: Vec<_> = if request.multiple {
dialog.pick_files().into_iter().flatten().collect()
} else {
dialog.pick_file().into_iter().collect()
};
files
}
enum Filters {
Extension(String),
Mime(String),
Audio,
Video,
Image,
}
impl Filters {
fn as_extensions(&self) -> Vec<&str> {
match self {
Filters::Extension(extension) => vec![extension.as_str()],
Filters::Mime(_) => vec![],
Filters::Audio => vec!["mp3", "wav", "ogg"],
Filters::Video => vec!["mp4", "webm"],
Filters::Image => vec!["png", "jpg", "jpeg", "gif", "webp"],
}
}
}
impl FromStr for Filters {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
if let Some(extension) = s.strip_prefix('.') {
Ok(Filters::Extension(extension.to_string()))
} else {
match s {
"audio/*" => Ok(Filters::Audio),
"video/*" => Ok(Filters::Video),
"image/*" => Ok(Filters::Image),
_ => Ok(Filters::Mime(s.to_string())),
}
}
}
}
+31 -2
View File
@@ -8,6 +8,7 @@ mod desktop_context;
mod escape;
mod eval;
mod events;
mod file_upload;
mod protocol;
mod shortcut;
mod waker;
@@ -19,14 +20,14 @@ pub use desktop_context::{
};
use desktop_context::{EventData, UserWindowEvent, WebviewQueue, WindowEventHandlers};
use dioxus_core::*;
use dioxus_html::HtmlEvent;
use dioxus_html::{native_bind::NativeFileEngine, FormData, HtmlEvent};
pub use eval::{use_eval, EvalResult};
use futures_util::{pin_mut, FutureExt};
use shortcut::ShortcutRegistry;
pub use shortcut::{use_global_shortcut, ShortcutHandle, ShortcutId, ShortcutRegistryError};
use std::collections::HashMap;
use std::rc::Rc;
use std::task::Waker;
use std::{collections::HashMap, sync::Arc};
pub use tao::dpi::{LogicalSize, PhysicalSize};
use tao::event_loop::{EventLoopProxy, EventLoopWindowTarget};
pub use tao::window::WindowBuilder;
@@ -264,6 +265,34 @@ pub fn launch_with_props<P: 'static>(root: Component<P>, props: P, cfg: Config)
}
}
EventData::Ipc(msg) if msg.method() == "file_diolog" => {
if let Ok(file_diolog) =
serde_json::from_value::<file_upload::FileDiologRequest>(msg.params())
{
let id = ElementId(file_diolog.target);
let event_name = &file_diolog.event;
let event_bubbles = file_diolog.bubbles;
let files = file_upload::get_file_event(&file_diolog);
let data = Rc::new(FormData {
value: Default::default(),
values: Default::default(),
files: Some(Arc::new(NativeFileEngine::new(files))),
});
let view = webviews.get_mut(&event.1).unwrap();
if event_name == "change&input" {
view.dom
.handle_event("input", data.clone(), id, event_bubbles);
view.dom.handle_event("change", data, id, event_bubbles);
} else {
view.dom.handle_event(event_name, data, id, event_bubbles);
}
send_edits(view.dom.render_immediate(), &view.webview);
}
}
_ => {}
},
Event::GlobalShortcutEvent(id) => shortcut_manager.call_handlers(id),
+27 -1
View File
@@ -9,10 +9,36 @@ use wry::{
};
fn module_loader(root_name: &str) -> String {
let js = INTERPRETER_JS.replace(
"/*POST_HANDLE_EDITS*/",
r#"// Prevent file inputs from opening the file dialog on click
let inputs = document.querySelectorAll("input");
for (let input of inputs) {
if (!input.getAttribute("data-dioxus-file-listener")) {
input.setAttribute("data-dioxus-file-listener", true);
input.addEventListener("click", (event) => {
let target = event.target;
// prevent file inputs from opening the file dialog on click
const type = target.getAttribute("type");
if (type === "file") {
let target_id = find_real_id(target);
if (target_id !== null) {
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 });
window.ipc.postMessage(message);
};
send("change&input");
}
event.preventDefault();
}
});
}
}"#,
);
format!(
r#"
<script>
{INTERPRETER_JS}
{js}
let rootname = "{root_name}";
let root = window.document.getElementById(rootname);