transit.rs 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. use std::{any::Any, rc::Rc};
  2. use crate::events::*;
  3. use dioxus_core::ElementId;
  4. use serde::{Deserialize, Serialize};
  5. #[derive(Serialize, Debug, Clone, PartialEq)]
  6. pub struct HtmlEvent {
  7. pub element: ElementId,
  8. pub name: String,
  9. pub bubbles: bool,
  10. pub data: EventData,
  11. }
  12. impl<'de> Deserialize<'de> for HtmlEvent {
  13. fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
  14. where
  15. D: serde::Deserializer<'de>,
  16. {
  17. #[derive(Deserialize, Debug, Clone)]
  18. struct Inner {
  19. element: ElementId,
  20. name: String,
  21. bubbles: bool,
  22. data: serde_value::Value,
  23. }
  24. let Inner {
  25. element,
  26. name,
  27. bubbles,
  28. data,
  29. } = Inner::deserialize(deserializer)?;
  30. Ok(HtmlEvent {
  31. data: fun_name(&name, data).unwrap(),
  32. element,
  33. bubbles,
  34. name,
  35. })
  36. }
  37. }
  38. fn fun_name(
  39. name: &str,
  40. data: serde_value::Value,
  41. ) -> Result<EventData, serde_value::DeserializerError> {
  42. use EventData::*;
  43. // a little macro-esque thing to make the code below more readable
  44. #[inline]
  45. fn de<'de, F>(f: serde_value::Value) -> Result<F, serde_value::DeserializerError>
  46. where
  47. F: Deserialize<'de>,
  48. {
  49. F::deserialize(f)
  50. }
  51. let data = match name {
  52. // Mouse
  53. "click" | "contextmenu" | "dblclick" | "doubleclick" | "mousedown" | "mouseenter"
  54. | "mouseleave" | "mousemove" | "mouseout" | "mouseover" | "mouseup" => Mouse(de(data)?),
  55. // Clipboard
  56. "copy" | "cut" | "paste" => Clipboard(de(data)?),
  57. // Composition
  58. "compositionend" | "compositionstart" | "compositionupdate" => Composition(de(data)?),
  59. // Keyboard
  60. "keydown" | "keypress" | "keyup" => Keyboard(de(data)?),
  61. // Focus
  62. "blur" | "focus" | "focusin" | "focusout" => Focus(de(data)?),
  63. // Form
  64. "change" | "input" | "invalid" | "reset" | "submit" => Form(de(data)?),
  65. // Drag
  66. "drag" | "dragend" | "dragenter" | "dragexit" | "dragleave" | "dragover" | "dragstart"
  67. | "drop" => Drag(de(data)?),
  68. // Pointer
  69. "pointerlockchange" | "pointerlockerror" | "pointerdown" | "pointermove" | "pointerup"
  70. | "pointerover" | "pointerout" | "pointerenter" | "pointerleave" | "gotpointercapture"
  71. | "lostpointercapture" => Pointer(de(data)?),
  72. // Selection
  73. "selectstart" | "selectionchange" | "select" => Selection(de(data)?),
  74. // Touch
  75. "touchcancel" | "touchend" | "touchmove" | "touchstart" => Touch(de(data)?),
  76. // Scroll
  77. "scroll" => Scroll(de(data)?),
  78. // Wheel
  79. "wheel" => Wheel(de(data)?),
  80. // Media
  81. "abort" | "canplay" | "canplaythrough" | "durationchange" | "emptied" | "encrypted"
  82. | "ended" | "interruptbegin" | "interruptend" | "loadeddata" | "loadedmetadata"
  83. | "loadstart" | "pause" | "play" | "playing" | "progress" | "ratechange" | "seeked"
  84. | "seeking" | "stalled" | "suspend" | "timeupdate" | "volumechange" | "waiting"
  85. | "loadend" | "timeout" => Media(de(data)?),
  86. // Animation
  87. "animationstart" | "animationend" | "animationiteration" => Animation(de(data)?),
  88. // Transition
  89. "transitionend" => Transition(de(data)?),
  90. // Toggle
  91. "toggle" => Toggle(de(data)?),
  92. "load" | "error" => Image(de(data)?),
  93. // Mounted
  94. "mounted" => Mounted,
  95. // 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";
  96. other => {
  97. return Err(serde_value::DeserializerError::UnknownVariant(
  98. other.to_string(),
  99. &[],
  100. ))
  101. }
  102. };
  103. Ok(data)
  104. }
  105. impl HtmlEvent {
  106. pub fn bubbles(&self) -> bool {
  107. event_bubbles(&self.name)
  108. }
  109. }
  110. #[derive(Deserialize, Serialize, Debug, Clone, PartialEq)]
  111. #[serde(untagged)]
  112. #[non_exhaustive]
  113. pub enum EventData {
  114. Mouse(MouseData),
  115. Clipboard(ClipboardData),
  116. Composition(CompositionData),
  117. Keyboard(KeyboardData),
  118. Focus(FocusData),
  119. Form(FormData),
  120. Drag(DragData),
  121. Pointer(PointerData),
  122. Selection(SelectionData),
  123. Touch(TouchData),
  124. Scroll(ScrollData),
  125. Wheel(WheelData),
  126. Media(MediaData),
  127. Animation(AnimationData),
  128. Transition(TransitionData),
  129. Toggle(ToggleData),
  130. Image(ImageData),
  131. Mounted,
  132. }
  133. impl EventData {
  134. pub fn into_any(self) -> Rc<dyn Any> {
  135. match self {
  136. EventData::Mouse(data) => Rc::new(data) as Rc<dyn Any>,
  137. EventData::Clipboard(data) => Rc::new(data) as Rc<dyn Any>,
  138. EventData::Composition(data) => Rc::new(data) as Rc<dyn Any>,
  139. EventData::Keyboard(data) => Rc::new(data) as Rc<dyn Any>,
  140. EventData::Focus(data) => Rc::new(data) as Rc<dyn Any>,
  141. EventData::Form(data) => Rc::new(data) as Rc<dyn Any>,
  142. EventData::Drag(data) => Rc::new(data) as Rc<dyn Any>,
  143. EventData::Pointer(data) => Rc::new(data) as Rc<dyn Any>,
  144. EventData::Selection(data) => Rc::new(data) as Rc<dyn Any>,
  145. EventData::Touch(data) => Rc::new(data) as Rc<dyn Any>,
  146. EventData::Scroll(data) => Rc::new(data) as Rc<dyn Any>,
  147. EventData::Wheel(data) => Rc::new(data) as Rc<dyn Any>,
  148. EventData::Media(data) => Rc::new(data) as Rc<dyn Any>,
  149. EventData::Animation(data) => Rc::new(data) as Rc<dyn Any>,
  150. EventData::Transition(data) => Rc::new(data) as Rc<dyn Any>,
  151. EventData::Toggle(data) => Rc::new(data) as Rc<dyn Any>,
  152. EventData::Image(data) => Rc::new(data) as Rc<dyn Any>,
  153. EventData::Mounted => Rc::new(MountedData::new(())) as Rc<dyn Any>,
  154. }
  155. }
  156. }
  157. #[test]
  158. fn test_back_and_forth() {
  159. let data = HtmlEvent {
  160. element: ElementId(0),
  161. data: EventData::Mouse(MouseData::default()),
  162. name: "click".to_string(),
  163. bubbles: true,
  164. };
  165. println!("{}", serde_json::to_string_pretty(&data).unwrap());
  166. let o = r#"
  167. {
  168. "element": 0,
  169. "name": "click",
  170. "bubbles": true,
  171. "data": {
  172. "alt_key": false,
  173. "button": 0,
  174. "buttons": 0,
  175. "client_x": 0,
  176. "client_y": 0,
  177. "ctrl_key": false,
  178. "meta_key": false,
  179. "offset_x": 0,
  180. "offset_y": 0,
  181. "page_x": 0,
  182. "page_y": 0,
  183. "screen_x": 0,
  184. "screen_y": 0,
  185. "shift_key": false
  186. }
  187. }
  188. "#;
  189. let p: HtmlEvent = serde_json::from_str(o).unwrap();
  190. assert_eq!(data, p);
  191. }