1use std::{any::Any, rc::Rc};
2
3use crate::events::*;
4use dioxus_core::ElementId;
5use serde::{Deserialize, Serialize};
6
7#[cfg(feature = "serialize")]
8#[derive(Serialize, Debug, PartialEq)]
9pub struct HtmlEvent {
10 pub element: ElementId,
11 pub name: String,
12 pub bubbles: bool,
13 pub data: EventData,
14}
15
16#[cfg(feature = "serialize")]
17impl<'de> Deserialize<'de> for HtmlEvent {
18 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
19 where
20 D: serde::Deserializer<'de>,
21 {
22 #[derive(Deserialize, Debug, Clone)]
23 struct Inner {
24 element: ElementId,
25 name: String,
26 bubbles: bool,
27 data: serde_json::Value,
28 }
29
30 let Inner {
31 element,
32 name,
33 bubbles,
34 data,
35 } = Inner::deserialize(deserializer)?;
36
37 let data = deserialize_raw(&name, &data).map_err(|e| {
39 serde::de::Error::custom(format!(
40 "Failed to deserialize event data for event {}: {}\n'{:#?}'",
41 name, e, data,
42 ))
43 })?;
44
45 Ok(HtmlEvent {
46 data,
47 element,
48 bubbles,
49 name,
50 })
51 }
52}
53
54#[cfg(feature = "serialize")]
55fn deserialize_raw(name: &str, data: &serde_json::Value) -> Result<EventData, serde_json::Error> {
56 match deserialize_raw_event(name, data)? {
57 Some(result) => Ok(result),
58 None => Err(serde::de::Error::custom(format!(
59 "Unknown event type: {name}"
60 ))),
61 }
62}
63
64#[cfg(feature = "serialize")]
65impl HtmlEvent {
66 pub fn bubbles(&self) -> bool {
67 self.bubbles
68 }
69}
70
71#[derive(Deserialize, Serialize, Debug, PartialEq)]
72#[serde(untagged)]
73#[non_exhaustive]
74pub enum EventData {
75 Cancel(SerializedCancelData),
76 Mouse(SerializedMouseData),
77 Clipboard(SerializedClipboardData),
78 Composition(SerializedCompositionData),
79 Keyboard(SerializedKeyboardData),
80 Focus(SerializedFocusData),
81 Form(SerializedFormData),
82 Drag(SerializedDragData),
83 Pointer(SerializedPointerData),
84 Selection(SerializedSelectionData),
85 Touch(SerializedTouchData),
86 Resize(SerializedResizeData),
87 Scroll(SerializedScrollData),
88 Visible(SerializedVisibleData),
89 Wheel(SerializedWheelData),
90 Media(SerializedMediaData),
91 Animation(SerializedAnimationData),
92 Transition(SerializedTransitionData),
93 Toggle(SerializedToggleData),
94 Image(SerializedImageData),
95 Mounted,
96}
97
98impl EventData {
99 pub fn into_any(self) -> Rc<dyn Any> {
100 match self {
101 EventData::Cancel(data) => {
102 Rc::new(PlatformEventData::new(Box::new(data))) as Rc<dyn Any>
103 }
104 EventData::Mouse(data) => {
105 Rc::new(PlatformEventData::new(Box::new(data))) as Rc<dyn Any>
106 }
107 EventData::Clipboard(data) => {
108 Rc::new(PlatformEventData::new(Box::new(data))) as Rc<dyn Any>
109 }
110 EventData::Composition(data) => {
111 Rc::new(PlatformEventData::new(Box::new(data))) as Rc<dyn Any>
112 }
113 EventData::Keyboard(data) => {
114 Rc::new(PlatformEventData::new(Box::new(data))) as Rc<dyn Any>
115 }
116 EventData::Focus(data) => {
117 Rc::new(PlatformEventData::new(Box::new(data))) as Rc<dyn Any>
118 }
119 EventData::Form(data) => Rc::new(PlatformEventData::new(Box::new(data))) as Rc<dyn Any>,
120 EventData::Drag(data) => Rc::new(PlatformEventData::new(Box::new(data))) as Rc<dyn Any>,
121 EventData::Pointer(data) => {
122 Rc::new(PlatformEventData::new(Box::new(data))) as Rc<dyn Any>
123 }
124 EventData::Selection(data) => {
125 Rc::new(PlatformEventData::new(Box::new(data))) as Rc<dyn Any>
126 }
127 EventData::Touch(data) => {
128 Rc::new(PlatformEventData::new(Box::new(data))) as Rc<dyn Any>
129 }
130 EventData::Resize(data) => {
131 Rc::new(PlatformEventData::new(Box::new(data))) as Rc<dyn Any>
132 }
133 EventData::Scroll(data) => {
134 Rc::new(PlatformEventData::new(Box::new(data))) as Rc<dyn Any>
135 }
136 EventData::Visible(data) => {
137 Rc::new(PlatformEventData::new(Box::new(data))) as Rc<dyn Any>
138 }
139 EventData::Wheel(data) => {
140 Rc::new(PlatformEventData::new(Box::new(data))) as Rc<dyn Any>
141 }
142 EventData::Media(data) => {
143 Rc::new(PlatformEventData::new(Box::new(data))) as Rc<dyn Any>
144 }
145 EventData::Animation(data) => {
146 Rc::new(PlatformEventData::new(Box::new(data))) as Rc<dyn Any>
147 }
148 EventData::Transition(data) => {
149 Rc::new(PlatformEventData::new(Box::new(data))) as Rc<dyn Any>
150 }
151 EventData::Toggle(data) => {
152 Rc::new(PlatformEventData::new(Box::new(data))) as Rc<dyn Any>
153 }
154 EventData::Image(data) => {
155 Rc::new(PlatformEventData::new(Box::new(data))) as Rc<dyn Any>
156 }
157 EventData::Mounted => {
158 Rc::new(PlatformEventData::new(Box::new(MountedData::new(())))) as Rc<dyn Any>
159 }
160 }
161 }
162}
163
164#[test]
165fn test_back_and_forth() {
166 let data = HtmlEvent {
167 element: ElementId(0),
168 data: EventData::Mouse(SerializedMouseData::default()),
169 name: "click".to_string(),
170 bubbles: true,
171 };
172
173 println!("{}", serde_json::to_string_pretty(&data).unwrap());
174
175 let o = r#"
176{
177 "element": 0,
178 "name": "click",
179 "bubbles": true,
180 "data": {
181 "alt_key": false,
182 "button": 0,
183 "buttons": 0,
184 "client_x": 0,
185 "client_y": 0,
186 "ctrl_key": false,
187 "meta_key": false,
188 "offset_x": 0,
189 "offset_y": 0,
190 "page_x": 0,
191 "page_y": 0,
192 "screen_x": 0,
193 "screen_y": 0,
194 "shift_key": false
195 }
196}
197 "#;
198
199 let p: HtmlEvent = serde_json::from_str(o).unwrap();
200
201 assert_eq!(data, p);
202}
203
204pub struct SerializedHtmlEventConverter;
206
207impl HtmlEventConverter for SerializedHtmlEventConverter {
208 fn convert_animation_data(&self, event: &PlatformEventData) -> AnimationData {
209 event
210 .downcast::<SerializedAnimationData>()
211 .cloned()
212 .unwrap()
213 .into()
214 }
215
216 fn convert_cancel_data(&self, event: &PlatformEventData) -> CancelData {
217 event
218 .downcast::<SerializedCancelData>()
219 .cloned()
220 .unwrap()
221 .into()
222 }
223
224 fn convert_clipboard_data(&self, event: &PlatformEventData) -> ClipboardData {
225 event
226 .downcast::<SerializedClipboardData>()
227 .cloned()
228 .unwrap()
229 .into()
230 }
231
232 fn convert_composition_data(&self, event: &PlatformEventData) -> CompositionData {
233 event
234 .downcast::<SerializedCompositionData>()
235 .cloned()
236 .unwrap()
237 .into()
238 }
239
240 fn convert_drag_data(&self, event: &PlatformEventData) -> DragData {
241 event
242 .downcast::<SerializedDragData>()
243 .cloned()
244 .unwrap()
245 .into()
246 }
247
248 fn convert_focus_data(&self, event: &PlatformEventData) -> FocusData {
249 event
250 .downcast::<SerializedFocusData>()
251 .cloned()
252 .unwrap()
253 .into()
254 }
255
256 fn convert_form_data(&self, event: &PlatformEventData) -> FormData {
257 event
258 .downcast::<SerializedFormData>()
259 .cloned()
260 .unwrap()
261 .into()
262 }
263
264 fn convert_image_data(&self, event: &PlatformEventData) -> ImageData {
265 event
266 .downcast::<SerializedImageData>()
267 .cloned()
268 .unwrap()
269 .into()
270 }
271
272 fn convert_keyboard_data(&self, event: &PlatformEventData) -> KeyboardData {
273 event
274 .downcast::<SerializedKeyboardData>()
275 .cloned()
276 .unwrap()
277 .into()
278 }
279
280 fn convert_media_data(&self, event: &PlatformEventData) -> MediaData {
281 event
282 .downcast::<SerializedMediaData>()
283 .cloned()
284 .unwrap()
285 .into()
286 }
287
288 fn convert_mounted_data(&self, _: &PlatformEventData) -> MountedData {
289 MountedData::from(())
290 }
291
292 fn convert_mouse_data(&self, event: &PlatformEventData) -> MouseData {
293 event
294 .downcast::<SerializedMouseData>()
295 .cloned()
296 .unwrap()
297 .into()
298 }
299
300 fn convert_pointer_data(&self, event: &PlatformEventData) -> PointerData {
301 event
302 .downcast::<SerializedPointerData>()
303 .cloned()
304 .unwrap()
305 .into()
306 }
307 fn convert_resize_data(&self, event: &PlatformEventData) -> ResizeData {
308 event
309 .downcast::<SerializedResizeData>()
310 .cloned()
311 .unwrap()
312 .into()
313 }
314
315 fn convert_scroll_data(&self, event: &PlatformEventData) -> ScrollData {
316 event
317 .downcast::<SerializedScrollData>()
318 .cloned()
319 .unwrap()
320 .into()
321 }
322
323 fn convert_selection_data(&self, event: &PlatformEventData) -> SelectionData {
324 event
325 .downcast::<SerializedSelectionData>()
326 .cloned()
327 .unwrap()
328 .into()
329 }
330
331 fn convert_toggle_data(&self, event: &PlatformEventData) -> ToggleData {
332 event
333 .downcast::<SerializedToggleData>()
334 .cloned()
335 .unwrap()
336 .into()
337 }
338
339 fn convert_touch_data(&self, event: &PlatformEventData) -> TouchData {
340 event
341 .downcast::<SerializedTouchData>()
342 .cloned()
343 .unwrap()
344 .into()
345 }
346
347 fn convert_transition_data(&self, event: &PlatformEventData) -> TransitionData {
348 event
349 .downcast::<SerializedTransitionData>()
350 .cloned()
351 .unwrap()
352 .into()
353 }
354
355 fn convert_visible_data(&self, event: &PlatformEventData) -> VisibleData {
356 event
357 .downcast::<SerializedVisibleData>()
358 .cloned()
359 .unwrap()
360 .into()
361 }
362
363 fn convert_wheel_data(&self, event: &PlatformEventData) -> WheelData {
364 event
365 .downcast::<SerializedWheelData>()
366 .cloned()
367 .unwrap()
368 .into()
369 }
370}