native file drop

This commit is contained in:
Jonathan Kelley 2024-03-05 14:11:12 -08:00
parent 78d16536a7
commit 624e58bd78
No known key found for this signature in database
GPG key ID: 1FBB50F7EB0A08BE
6 changed files with 115 additions and 8 deletions

View file

@ -2,7 +2,7 @@ use crate::{
config::{Config, WindowCloseBehaviour},
element::DesktopElement,
event_handlers::WindowEventHandlers,
file_upload::{DesktopFileUploadForm, FileDialogRequest},
file_upload::{DesktopFileDragEvent, DesktopFileUploadForm, FileDialogRequest},
ipc::{EventData, IpcMessage, UserWindowEvent},
query::QueryResult,
shortcut::{GlobalHotKeyEvent, ShortcutRegistry},
@ -11,7 +11,7 @@ use crate::{
use crossbeam_channel::Receiver;
use dioxus_core::ElementId;
use dioxus_core::VirtualDom;
use dioxus_html::{native_bind::NativeFileEngine, HtmlEvent, PlatformEventData};
use dioxus_html::{native_bind::NativeFileEngine, HasFileData, HtmlEvent, PlatformEventData};
use std::{
cell::{Cell, RefCell},
collections::HashMap,
@ -231,6 +231,7 @@ impl App {
let view = self.webviews.get_mut(&id).unwrap();
let query = view.desktop_context.query.clone();
let recent_file = view.desktop_context.file_hover.clone();
// check for a mounted event placeholder and replace it with a desktop specific element
let as_any = match data {
@ -238,6 +239,25 @@ impl App {
let element = DesktopElement::new(element, view.desktop_context.clone(), query);
Rc::new(PlatformEventData::new(Box::new(element)))
}
dioxus_html::EventData::Drag(ref drag) => {
// we want to override this with a native file engine, provided by the most recent drag event
if drag.files().is_some() {
let file_event = recent_file.current().unwrap();
let paths = match file_event {
wry::FileDropEvent::Hovered { paths, position } => paths,
wry::FileDropEvent::Dropped { paths, position } => paths,
_ => vec![],
};
let files = Arc::new(NativeFileEngine::new(paths));
let event = DesktopFileDragEvent {
mouse: drag.mouse.clone(),
files,
};
Rc::new(PlatformEventData::new(Box::new(event)))
} else {
data.into_any()
}
}
_ => data.into_any(),
};

View file

@ -1,6 +1,9 @@
//! Convert a serialized event to an event trigger
use crate::{element::DesktopElement, file_upload::DesktopFileUploadForm};
use crate::{
element::DesktopElement,
file_upload::{DesktopFileDragEvent, DesktopFileUploadForm},
};
use dioxus_html::*;
pub(crate) struct SerializedHtmlEventConverter;
@ -31,8 +34,14 @@ impl HtmlEventConverter for SerializedHtmlEventConverter {
}
fn convert_drag_data(&self, event: &PlatformEventData) -> DragData {
// Attempt a simple serialized data conversion
if let Some(_data) = event.downcast::<SerializedDragData>() {
return _data.clone().into();
}
// If that failed then it's a file drag form
event
.downcast::<SerializedDragData>()
.downcast::<DesktopFileDragEvent>()
.cloned()
.unwrap()
.into()

View file

@ -1,6 +1,16 @@
#![allow(unused)]
use dioxus_html::{native_bind::NativeFileEngine, FileEngine, HasFileData, HasFormData};
use dioxus_html::{
geometry::{ClientPoint, Coordinates, ElementPoint, PagePoint, ScreenPoint},
input_data::{MouseButton, MouseButtonSet},
native_bind::NativeFileEngine,
point_interaction::{
InteractionElementOffset, InteractionLocation, ModifiersInteraction, PointerInteraction,
},
prelude::{SerializedMouseData, SerializedPointInteraction},
FileEngine, HasDragData, HasFileData, HasFormData, HasMouseData,
};
use muda::accelerator::Modifiers;
use serde::Deserialize;
use std::{cell::Cell, path::PathBuf, rc::Rc, str::FromStr, sync::Arc};
use wry::FileDropEvent;
@ -152,4 +162,72 @@ impl NativeFileHover {
pub fn set(&self, event: FileDropEvent) {
self.event.set(Some(event));
}
pub fn current(&self) -> Option<FileDropEvent> {
self.event.as_ref().clone().take()
}
}
#[derive(Clone)]
pub(crate) struct DesktopFileDragEvent {
pub mouse: SerializedPointInteraction,
pub files: Arc<NativeFileEngine>,
}
impl HasFileData for DesktopFileDragEvent {
fn files(&self) -> Option<Arc<dyn FileEngine>> {
Some(self.files.clone())
}
}
impl HasDragData for DesktopFileDragEvent {
fn as_any(&self) -> &dyn std::any::Any {
self
}
}
impl HasMouseData for DesktopFileDragEvent {
fn as_any(&self) -> &dyn std::any::Any {
self
}
}
impl InteractionLocation for DesktopFileDragEvent {
fn client_coordinates(&self) -> ClientPoint {
self.mouse.client_coordinates()
}
fn page_coordinates(&self) -> PagePoint {
self.mouse.page_coordinates()
}
fn screen_coordinates(&self) -> ScreenPoint {
self.mouse.screen_coordinates()
}
}
impl InteractionElementOffset for DesktopFileDragEvent {
fn element_coordinates(&self) -> ElementPoint {
self.mouse.element_coordinates()
}
fn coordinates(&self) -> Coordinates {
self.mouse.coordinates()
}
}
impl ModifiersInteraction for DesktopFileDragEvent {
fn modifiers(&self) -> Modifiers {
self.mouse.modifiers()
}
}
impl PointerInteraction for DesktopFileDragEvent {
fn held_buttons(&self) -> MouseButtonSet {
self.mouse.held_buttons()
}
fn trigger_button(&self) -> Option<MouseButton> {
self.mouse.trigger_button()
}
}

View file

@ -109,7 +109,7 @@ impl PointerInteraction for DragData {
/// A serialized version of DragData
#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Clone)]
pub struct SerializedDragData {
mouse: crate::point_interaction::SerializedPointInteraction,
pub mouse: crate::point_interaction::SerializedPointInteraction,
#[serde(default)]
files: Option<crate::file_data::SerializedFileEngine>,

View file

@ -50,7 +50,7 @@ pub trait ModifiersInteraction {
#[cfg(feature = "serialize")]
#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Clone, Default)]
pub(crate) struct SerializedPointInteraction {
pub struct SerializedPointInteraction {
pub alt_key: bool,
/// The button number that was pressed (if applicable) when the mouse event was fired.

View file

@ -1 +1 @@
2617078454438840343
13140749608285001344