Files
dioxus/packages/interpreter/src/ts/serialize.ts
T

219 lines
6.4 KiB
TypeScript

// Handle serialization of the event data across the IPC boundarytype SerialziedEvent = {};
import { retriveSelectValue, retriveValues } from "./form";
export type AppTouchEvent = TouchEvent;
export type SerializedEvent = {
values?: { [key: string]: FormDataEntryValue[] };
value?: string;
[key: string]: any;
};
export function serializeEvent(event: Event, target: EventTarget): SerializedEvent {
let contents = {};
// merge the object into the contents
let extend = (obj: any) => (contents = { ...contents, ...obj });
if (event instanceof WheelEvent) { extend(serializeWheelEvent(event)) };
if (event instanceof MouseEvent) { extend(serializeMouseEvent(event)) }
if (event instanceof KeyboardEvent) { extend(serializeKeyboardEvent(event)) }
if (event instanceof InputEvent) { extend(serializeInputEvent(event, target)) }
if (event instanceof PointerEvent) { extend(serializePointerEvent(event)) }
if (event instanceof AnimationEvent) { extend(serializeAnimationEvent(event)) }
if (event instanceof TransitionEvent) { extend({ property_name: event.propertyName, elapsed_time: event.elapsedTime, pseudo_element: event.pseudoElement, }) }
if (event instanceof CompositionEvent) { extend({ data: event.data, }) }
if (event instanceof DragEvent) { extend(serializeDragEvent(event)) }
if (event instanceof FocusEvent) { extend({}) }
if (event instanceof ClipboardEvent) { extend({}) }
// safari is quirky and doesn't have TouchEvent
if (typeof TouchEvent !== 'undefined' && event instanceof TouchEvent) { extend(serializeTouchEvent(event)); }
if (event.type === "submit" || event.type === "reset" || event.type === "click" || event.type === "change" || event.type === "input") {
extend(serializeInputEvent(event as InputEvent, target));
}
// If there's any files, we need to serialize them
if (event instanceof DragEvent) {
// let files: { [key: string]: Uint8Array } = {};
// if (event.dataTransfer && event.dataTransfer.files) {
// files["a"] = new Uint8Array(0);
// // files = {
// // entries: Array.from(event.dataTransfer.files).map((file) => {
// // return {
// // name: file.name,
// // type: file.type,
// // size: file.size,
// // last_modified: file.lastModified,
// // };
// // }
// // };
// // files = await serializeFileList(event.dataTransfer.files);
// }
// extend({ files: files });
}
return contents;
}
function serializeInputEvent(event: InputEvent, target: EventTarget): SerializedEvent {
let contents: SerializedEvent = {};
// Attempt to retrieve the values from the form
if (target instanceof HTMLElement) {
let values = retriveValues(event, target);
contents.values = values.values;
contents.valid = values.valid;
}
if (event.target instanceof HTMLInputElement) {
let target = event.target;
let value = target.value ?? target.textContent ?? "";
if (target.type === "checkbox") {
value = target.checked ? "true" : "false";
} else if (target.type === "radio") {
value = target.value;
}
contents.value = value;
}
if (event.target instanceof HTMLTextAreaElement) {
contents.value = event.target.value;
}
if (event.target instanceof HTMLSelectElement) {
contents.value = retriveSelectValue(event.target).join(",");
}
// Ensure the serializer isn't quirky
if (contents.value === undefined) {
contents.value = "";
}
return contents;
}
function serializeWheelEvent(event: WheelEvent): SerializedEvent {
return {
delta_x: event.deltaX,
delta_y: event.deltaY,
delta_z: event.deltaZ,
delta_mode: event.deltaMode,
};
}
function serializeTouchEvent(event: TouchEvent): SerializedEvent {
return {
alt_key: event.altKey,
ctrl_key: event.ctrlKey,
meta_key: event.metaKey,
shift_key: event.shiftKey,
changed_touches: event.changedTouches,
target_touches: event.targetTouches,
touches: event.touches,
};
}
function serializePointerEvent(event: PointerEvent): SerializedEvent {
return {
alt_key: event.altKey,
button: event.button,
buttons: event.buttons,
client_x: event.clientX,
client_y: event.clientY,
ctrl_key: event.ctrlKey,
meta_key: event.metaKey,
page_x: event.pageX,
page_y: event.pageY,
screen_x: event.screenX,
screen_y: event.screenY,
shift_key: event.shiftKey,
pointer_id: event.pointerId,
width: event.width,
height: event.height,
pressure: event.pressure,
tangential_pressure: event.tangentialPressure,
tilt_x: event.tiltX,
tilt_y: event.tiltY,
twist: event.twist,
pointer_type: event.pointerType,
is_primary: event.isPrimary,
};
}
function serializeMouseEvent(event: MouseEvent): SerializedEvent {
return {
alt_key: event.altKey,
button: event.button,
buttons: event.buttons,
client_x: event.clientX,
client_y: event.clientY,
ctrl_key: event.ctrlKey,
meta_key: event.metaKey,
offset_x: event.offsetX,
offset_y: event.offsetY,
page_x: event.pageX,
page_y: event.pageY,
screen_x: event.screenX,
screen_y: event.screenY,
shift_key: event.shiftKey,
};
}
function serializeKeyboardEvent(event: KeyboardEvent): SerializedEvent {
return {
char_code: event.charCode,
is_composing: event.isComposing,
key: event.key,
alt_key: event.altKey,
ctrl_key: event.ctrlKey,
meta_key: event.metaKey,
key_code: event.keyCode,
shift_key: event.shiftKey,
location: event.location,
repeat: event.repeat,
which: event.which,
code: event.code,
};
}
function serializeAnimationEvent(event: AnimationEvent): SerializedEvent {
return {
animation_name: event.animationName,
elapsed_time: event.elapsedTime,
pseudo_element: event.pseudoElement,
};
}
function serializeDragEvent(event: DragEvent): SerializedEvent {
let files = undefined;
// On desktop if there is file data, we insert it from wry. We just add a placeholder to let the rust side of dioxus know there's files
if (
event.dataTransfer &&
event.dataTransfer.files &&
event.dataTransfer.files.length > 0
) {
files = {
files: { placeholder: [] },
};
}
return {
mouse: {
alt_key: event.altKey,
ctrl_key: event.ctrlKey,
meta_key: event.metaKey,
shift_key: event.shiftKey,
...serializeMouseEvent(event),
},
files,
};
}