#![allow(unused)] 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; #[derive(Debug, Deserialize)] pub(crate) struct FileDialogRequest { #[serde(default)] accept: Option, multiple: bool, directory: bool, pub event: String, pub target: usize, pub bubbles: bool, } #[allow(unused)] impl FileDialogRequest { #[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(&self) -> Vec { 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(&self) -> Vec { fn get_file_event_for_folder( request: &FileDialogRequest, dialog: rfd::FileDialog, ) -> Vec { if request.multiple { dialog.pick_folders().into_iter().flatten().collect() } else { dialog.pick_folder().into_iter().collect() } } fn get_file_event_for_file( request: &FileDialogRequest, mut dialog: rfd::FileDialog, ) -> Vec { let filters: Vec<_> = request .accept .as_deref() .unwrap_or_default() .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 } let dialog = rfd::FileDialog::new(); if self.directory { get_file_event_for_folder(self, dialog) } else { get_file_event_for_file(self, dialog) } } } 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 { 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())), } } } } #[derive(Clone)] pub(crate) struct DesktopFileUploadForm { pub files: Arc, } impl HasFileData for DesktopFileUploadForm { fn files(&self) -> Option> { Some(self.files.clone()) } } impl HasFormData for DesktopFileUploadForm { fn as_any(&self) -> &dyn std::any::Any { self } } #[derive(Default, Clone)] pub struct NativeFileHover { event: Rc>>, } impl NativeFileHover { pub fn set(&self, event: FileDropEvent) { self.event.set(Some(event)); } pub fn current(&self) -> Option { self.event.as_ref().clone().take() } } #[derive(Clone)] pub(crate) struct DesktopFileDragEvent { pub mouse: SerializedPointInteraction, pub files: Arc, } impl HasFileData for DesktopFileDragEvent { fn files(&self) -> Option> { 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 { self.mouse.trigger_button() } }