#Why does `ondrop` take a DragEvent that downcasts to `MouseEvent` instead of `DragEvent`?

1 messages · Page 1 of 1 (latest)

vocal gull
#

https://github.com/DioxusLabs/dioxus/blob/9ebcbc6bd9e1b1af9b141d2dd8ed6c816b42607e/packages/html/src/events/drag.rs#L247 defines ondrop through the macro. I am not yet able to follow the macro's logic of converting from web_sys events into dioxus events, but I do know from experimentation that ondrop is getting a dioxus::DragEvent that downcasts to web_sys::MouseEvent, that somehow has files, rather than a web_sys::DragEvent. See code in thread.

This is a problem for me because I am doing things that the current HasFileData does not seem to support, specifically directory handling (webkitdirectory), and I want to loop over the files with their full directory paths. Right now I only get the name of the folder dropped, not the full list of files with paths, as I would expect to be the case per (related but not quite the same): https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/webkitdirectory#understanding_the_results

Perhaps there is some place in dioxus where the directory items are gotten from drops ala https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API/File_drag_and_drop#process_the_drop ?

As per previous discussion e.g. by @leaden nebula ala https://github.com/DioxusLabs/dioxus/pull/2323#pullrequestreview-2055565567 this is further evidence that a better file interface needs to be developed, but for now, I'm comfortable figuring out parts of that interface by building it manually for just my application, and then I'll happily migrate it over to dioxus itself.

But I'd still like to know if this is deliberate for some reason or a bug/missed feature, somehow. Perhaps the solution is simply to "fix" drag & drop event files to have the full paths as per the above, or perhaps it is to downcast to DragEvent instead of MouseEvent (tho, perhaps relevantly, DragEvent inherits from MouseEvent per MDN)

MDN Web Docs

The HTMLInputElement.webkitdirectory is a property
that reflects the webkitdirectory HTML attribute
and indicates that the element should let the user select directories instead of files.
When a directory is selected, the directory and its entire hierarchy of contents are included in the set of selected items.
The selected file system e...

GitHub

This allows file sizes to be checked before loading the entire file into memory (e.g. with read_file) when it might be too big. (And without requesting the native file to do this check manually.)

MDN Web Docs

HTML Drag and Drop interfaces enable web applications to drag and drop files on a web page. This document describes how an application can accept one or more files that are dragged from the underlying platform's file manager and dropped on a web page.

GitHub

Fullstack app framework for web, desktop, mobile, and more. - DioxusLabs/dioxus

#

Demo repro:

#![allow(non_snake_case)]

use dioxus::prelude::*;
use dioxus_logger::tracing::{info, Level};

fn main() {
    // Init logger
    dioxus_logger::init(Level::INFO).expect("failed to init logger");
    info!("starting app");
    launch(App);
}

#[component]
fn App() -> Element {
    rsx! {
        div {
            style: "width: full; height: 40px; background-color: green;",
            ondragover: move |evt: DragEvent| {
                evt.prevent_default();
                evt.stop_propagation();

                if let Some(_) = evt.downcast::<web_sys::DragEvent>() {
                    info!("dragover Drag");
                }
                if let Some(_) = evt.downcast::<web_sys::MouseEvent>() {
                    info!("dragover Mouse");
                }
            },
            ondrop: move |evt: DragEvent| {
                evt.prevent_default();

                if let Some(_) = evt.downcast::<web_sys::DragEvent>() {
                    info!("drop Drag");
                }
                if let Some(_) = evt.downcast::<web_sys::MouseEvent>() {
                    info!("drop Mouse");
                }
            }
        }
    }
}

Note that this requires in Cargo.toml:

dioxus = { path = "../dioxus/packages/dioxus", features = ["web"] }
web-sys = { version = "0.3.70", features = ["DataTransfer", "DragEvent"] }
#

In the demo/repro, you will only see logs of "dragover Mouse" and "drop Mouse" never "drop/dragover Drag", indicating that only web_sys::MouseEvents are there, and not DragEvents

#

I tested in both Firefox and Chrome

#

In particular, I believe something here needs to be incorporated: https://developer.mozilla.org/en-US/docs/Web/API/DataTransferItem 's https://developer.mozilla.org/en-US/docs/Web/API/DataTransferItem/webkitGetAsEntry -- to not just read the files, but also the items as potential directories

MDN Web Docs

The DataTransferItem object represents one drag data item. During a drag operation, each DragEvent has a dataTransfer property which contains a list of drag data items. Each item in the list is a DataTransferItem object.

MDN Web Docs

If the item described by the DataTransferItem is a file, webkitGetAsEntry() returns a FileSystemFileEntry or FileSystemDirectoryEntry representing it. If the item isn't a file, null is returned.

#

But I cannot do that with MouseEvent, I need DragEvent

leaden nebula
#

DragEvent should always downcast to the same type

#

But I think it should be a drag event

vocal gull
#

And I expect it has worked so far because the raw event is a dragevent, so you can get files off of it, but also inherits from mouseevent, so you can pass it as such. But it's dropping extra data that way

#

I would happily work on all these problems myslf, if I knew where to work on them. I did a lot of digging already but I did not even discover that WebEventExt nor anything that showed me how these file lists were built for actual events. Point me at such things and I'll gladly put up a PR

leaden nebula
vocal gull
#

I put up a pr for what seems like the basics, I'll return for more digging later.