feat: add proper event type
This commit is contained in:
1 parent
aa71c111cd
commit
50faa7dd08
22 files changed
+273
-47
No files matched your search
@@ -0,0 +1,217 @@
|
||||
use std::{any::Any, rc::Rc};
|
||||
|
||||
use crate::events::*;
|
||||
use dioxus_core::ElementId;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Serialize, Debug, Clone, PartialEq)]
|
||||
pub struct HtmlEvent {
|
||||
pub element: ElementId,
|
||||
pub name: String,
|
||||
pub bubbles: bool,
|
||||
pub data: EventData,
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for HtmlEvent {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
#[derive(Deserialize, Debug, Clone)]
|
||||
struct Inner {
|
||||
element: ElementId,
|
||||
name: String,
|
||||
bubbles: bool,
|
||||
data: serde_value::Value,
|
||||
}
|
||||
|
||||
let Inner {
|
||||
element,
|
||||
name,
|
||||
bubbles,
|
||||
data,
|
||||
} = Inner::deserialize(deserializer)?;
|
||||
|
||||
Ok(HtmlEvent {
|
||||
data: fun_name(&name, data).unwrap(),
|
||||
element,
|
||||
bubbles,
|
||||
name,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn fun_name(
|
||||
name: &str,
|
||||
data: serde_value::Value,
|
||||
) -> Result<EventData, serde_value::DeserializerError> {
|
||||
use EventData::*;
|
||||
|
||||
// a little macro-esque thing to make the code below more readable
|
||||
#[inline]
|
||||
fn de<'de, F>(f: serde_value::Value) -> Result<F, serde_value::DeserializerError>
|
||||
where
|
||||
F: Deserialize<'de>,
|
||||
{
|
||||
F::deserialize(f)
|
||||
}
|
||||
|
||||
let data = match name {
|
||||
// Mouse
|
||||
"click" | "contextmenu" | "dblclick" | "doubleclick" | "mousedown" | "mouseenter"
|
||||
| "mouseleave" | "mousemove" | "mouseout" | "mouseover" | "mouseup" => Mouse(de(data)?),
|
||||
|
||||
// Clipboard
|
||||
"copy" | "cut" | "paste" => Clipboard(de(data)?),
|
||||
|
||||
// Composition
|
||||
"compositionend" | "compositionstart" | "compositionupdate" => Composition(de(data)?),
|
||||
|
||||
// Keyboard
|
||||
"keydown" | "keypress" | "keyup" => Keyboard(de(data)?),
|
||||
|
||||
// Focus
|
||||
"blur" | "focus" | "focusin" | "focusout" => Focus(de(data)?),
|
||||
|
||||
// Form
|
||||
"change" | "input" | "invalid" | "reset" | "submit" => Form(de(data)?),
|
||||
|
||||
// Drag
|
||||
"drag" | "dragend" | "dragenter" | "dragexit" | "dragleave" | "dragover" | "dragstart"
|
||||
| "drop" => Drag(de(data)?),
|
||||
|
||||
// Pointer
|
||||
"pointerlockchange" | "pointerlockerror" | "pointerdown" | "pointermove" | "pointerup"
|
||||
| "pointerover" | "pointerout" | "pointerenter" | "pointerleave" | "gotpointercapture"
|
||||
| "lostpointercapture" => Pointer(de(data)?),
|
||||
|
||||
// Selection
|
||||
"selectstart" | "selectionchange" | "select" => Selection(de(data)?),
|
||||
|
||||
// Touch
|
||||
"touchcancel" | "touchend" | "touchmove" | "touchstart" => Touch(de(data)?),
|
||||
|
||||
// Srcoll
|
||||
"scroll" => Scroll(de(data)?),
|
||||
|
||||
// Wheel
|
||||
"wheel" => Wheel(de(data)?),
|
||||
|
||||
// Media
|
||||
"abort" | "canplay" | "canplaythrough" | "durationchange" | "emptied" | "encrypted"
|
||||
| "ended" | "interruptbegin" | "interruptend" | "loadeddata" | "loadedmetadata"
|
||||
| "loadstart" | "pause" | "play" | "playing" | "progress" | "ratechange" | "seeked"
|
||||
| "seeking" | "stalled" | "suspend" | "timeupdate" | "volumechange" | "waiting"
|
||||
| "error" | "load" | "loadend" | "timeout" => Media(de(data)?),
|
||||
|
||||
// Animation
|
||||
"animationstart" | "animationend" | "animationiteration" => Animation(de(data)?),
|
||||
|
||||
// Transition
|
||||
"transitionend" => Transition(de(data)?),
|
||||
|
||||
// Toggle
|
||||
"toggle" => Toggle(de(data)?),
|
||||
|
||||
// ImageData => "load" | "error";
|
||||
// OtherData => "abort" | "afterprint" | "beforeprint" | "beforeunload" | "hashchange" | "languagechange" | "message" | "offline" | "online" | "pagehide" | "pageshow" | "popstate" | "rejectionhandled" | "storage" | "unhandledrejection" | "unload" | "userproximity" | "vrdisplayactivate" | "vrdisplayblur" | "vrdisplayconnect" | "vrdisplaydeactivate" | "vrdisplaydisconnect" | "vrdisplayfocus" | "vrdisplaypointerrestricted" | "vrdisplaypointerunrestricted" | "vrdisplaypresentchange";
|
||||
other => {
|
||||
return Err(serde_value::DeserializerError::UnknownVariant(
|
||||
other.to_string(),
|
||||
&[],
|
||||
))
|
||||
}
|
||||
};
|
||||
|
||||
Ok(data)
|
||||
}
|
||||
|
||||
impl HtmlEvent {
|
||||
pub fn bubbles(&self) -> bool {
|
||||
event_bubbles(&self.name)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, Debug, Clone, PartialEq)]
|
||||
#[serde(untagged)]
|
||||
pub enum EventData {
|
||||
Mouse(MouseData),
|
||||
Clipboard(ClipboardData),
|
||||
Composition(CompositionData),
|
||||
Keyboard(KeyboardData),
|
||||
Focus(FocusData),
|
||||
Form(FormData),
|
||||
Drag(DragData),
|
||||
Pointer(PointerData),
|
||||
Selection(SelectionData),
|
||||
Touch(TouchData),
|
||||
Scroll(ScrollData),
|
||||
Wheel(WheelData),
|
||||
Media(MediaData),
|
||||
Animation(AnimationData),
|
||||
Transition(TransitionData),
|
||||
Toggle(ToggleData),
|
||||
}
|
||||
|
||||
impl EventData {
|
||||
pub fn into_any(self) -> Rc<dyn Any> {
|
||||
match self {
|
||||
EventData::Mouse(data) => Rc::new(data) as Rc<dyn Any>,
|
||||
EventData::Clipboard(data) => Rc::new(data) as Rc<dyn Any>,
|
||||
EventData::Composition(data) => Rc::new(data) as Rc<dyn Any>,
|
||||
EventData::Keyboard(data) => Rc::new(data) as Rc<dyn Any>,
|
||||
EventData::Focus(data) => Rc::new(data) as Rc<dyn Any>,
|
||||
EventData::Form(data) => Rc::new(data) as Rc<dyn Any>,
|
||||
EventData::Drag(data) => Rc::new(data) as Rc<dyn Any>,
|
||||
EventData::Pointer(data) => Rc::new(data) as Rc<dyn Any>,
|
||||
EventData::Selection(data) => Rc::new(data) as Rc<dyn Any>,
|
||||
EventData::Touch(data) => Rc::new(data) as Rc<dyn Any>,
|
||||
EventData::Scroll(data) => Rc::new(data) as Rc<dyn Any>,
|
||||
EventData::Wheel(data) => Rc::new(data) as Rc<dyn Any>,
|
||||
EventData::Media(data) => Rc::new(data) as Rc<dyn Any>,
|
||||
EventData::Animation(data) => Rc::new(data) as Rc<dyn Any>,
|
||||
EventData::Transition(data) => Rc::new(data) as Rc<dyn Any>,
|
||||
EventData::Toggle(data) => Rc::new(data) as Rc<dyn Any>,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_back_and_forth() {
|
||||
let data = HtmlEvent {
|
||||
element: ElementId(0),
|
||||
data: EventData::Mouse(MouseData::default()),
|
||||
name: "click".to_string(),
|
||||
bubbles: true,
|
||||
};
|
||||
|
||||
println!("{}", serde_json::to_string_pretty(&data).unwrap());
|
||||
|
||||
let o = r#"
|
||||
{
|
||||
"element": 0,
|
||||
"name": "click",
|
||||
"bubbles": true,
|
||||
"data": {
|
||||
"alt_key": false,
|
||||
"button": 0,
|
||||
"buttons": 0,
|
||||
"client_x": 0,
|
||||
"client_y": 0,
|
||||
"ctrl_key": false,
|
||||
"meta_key": false,
|
||||
"offset_x": 0,
|
||||
"offset_y": 0,
|
||||
"page_x": 0,
|
||||
"page_y": 0,
|
||||
"screen_x": 0,
|
||||
"screen_y": 0,
|
||||
"shift_key": false
|
||||
}
|
||||
}
|
||||
"#;
|
||||
|
||||
let p: HtmlEvent = serde_json::from_str(o).unwrap();
|
||||
|
||||
assert_eq!(data, p);
|
||||
}
|
||||
Reference in new issue
Block a user