Pārlūkot izejas kodu

native file drop

Jonathan Kelley 1 gadu atpakaļ
vecāks
revīzija
624e58bd78

+ 22 - 2
packages/desktop/src/app.rs

@@ -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(),
         };
 

+ 11 - 2
packages/desktop/src/events.rs

@@ -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()

+ 79 - 1
packages/desktop/src/file_upload.rs

@@ -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()
+    }
 }

+ 1 - 1
packages/html/src/events/drag.rs

@@ -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>,

+ 1 - 1
packages/html/src/point_interaction.rs

@@ -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.

+ 1 - 1
packages/interpreter/src/js/hash.txt

@@ -1 +1 @@
-2617078454438840343
+13140749608285001344