Major frontend code cleanup (#452)

Many large changes, including:
- TypeScript enums are now string unions throughout
- Strong type-checking throughout the TS and Vue codebase
- Vue component props now all specify `as PropType<...>`
- Usage of annotated return types on all functions
- Sorting of JS import statements
- Explicit usage of Vue bind attribute function call arguments (`@click="foo"` is now `@click=(e) => foo(e)`)
- Much improved code quality related to the color picker
- Consistent camelCase Vue bind and v-model attributes
- Consistent Vue HTML attribute strings with single quotes
- Bug fix and clarity improvement with incorrect hint class parameters
- Empty Vue component objects like `props: {}` and `components: {}` removed
This commit is contained in:
Keavon Chambers
2022-01-02 06:00:02 -08:00
parent 6662a9a04f
commit 2c8d70acb4
53 changed files with 842 additions and 946 deletions
+24 -23
View File
@@ -1,6 +1,6 @@
import { DialogState } from "@/state/dialog";
import { FullscreenState } from "@/state/fullscreen";
import { DocumentsState } from "@/state/documents";
import { FullscreenState } from "@/state/fullscreen";
import { EditorState } from "@/state/wasm-loader";
type EventName = keyof HTMLElementEventMap | keyof WindowEventHandlersEventMap;
@@ -9,20 +9,21 @@ interface EventListenerTarget {
removeEventListener: typeof window.removeEventListener;
}
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
export function createInputManager(editor: EditorState, container: HTMLElement, dialog: DialogState, document: DocumentsState, fullscreen: FullscreenState) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const listeners: { target: EventListenerTarget; eventName: EventName; action: (event: any) => void; options?: boolean | AddEventListenerOptions }[] = [
{ target: window, eventName: "resize", action: () => onWindowResize(container) },
{ target: window, eventName: "beforeunload", action: (e) => onBeforeUnload(e) },
{ target: window.document, eventName: "contextmenu", action: (e) => e.preventDefault() },
{ target: window.document, eventName: "fullscreenchange", action: () => fullscreen.fullscreenModeChanged() },
{ target: window, eventName: "keyup", action: (e) => onKeyUp(e) },
{ target: window, eventName: "keydown", action: (e) => onKeyDown(e) },
{ target: window, eventName: "pointermove", action: (e) => onPointerMove(e) },
{ target: window, eventName: "pointerdown", action: (e) => onPointerDown(e) },
{ target: window, eventName: "pointerup", action: (e) => onPointerUp(e) },
{ target: window, eventName: "mousedown", action: (e) => onMouseDown(e) },
{ target: window, eventName: "wheel", action: (e) => onMouseScroll(e), options: { passive: false } },
{ target: window, eventName: "resize", action: (): void => onWindowResize(container) },
{ target: window, eventName: "beforeunload", action: (e: BeforeUnloadEvent): void => onBeforeUnload(e) },
{ target: window.document, eventName: "contextmenu", action: (e: MouseEvent): void => e.preventDefault() },
{ target: window.document, eventName: "fullscreenchange", action: (): void => fullscreen.fullscreenModeChanged() },
{ target: window, eventName: "keyup", action: (e: KeyboardEvent): void => onKeyUp(e) },
{ target: window, eventName: "keydown", action: (e: KeyboardEvent): void => onKeyDown(e) },
{ target: window, eventName: "pointermove", action: (e: PointerEvent): void => onPointerMove(e) },
{ target: window, eventName: "pointerdown", action: (e: PointerEvent): void => onPointerDown(e) },
{ target: window, eventName: "pointerup", action: (e: PointerEvent): void => onPointerUp(e) },
{ target: window, eventName: "mousedown", action: (e: MouseEvent): void => onMouseDown(e) },
{ target: window, eventName: "wheel", action: (e: WheelEvent): void => onMouseScroll(e), options: { passive: false } },
];
let viewportPointerInteractionOngoing = false;
@@ -60,7 +61,7 @@ export function createInputManager(editor: EditorState, container: HTMLElement,
return true;
};
const onKeyDown = (e: KeyboardEvent) => {
const onKeyDown = (e: KeyboardEvent): void => {
const key = getLatinKey(e);
if (!key) return;
@@ -82,7 +83,7 @@ export function createInputManager(editor: EditorState, container: HTMLElement,
}
};
const onKeyUp = (e: KeyboardEvent) => {
const onKeyUp = (e: KeyboardEvent): void => {
const key = getLatinKey(e);
if (!key) return;
@@ -95,14 +96,14 @@ export function createInputManager(editor: EditorState, container: HTMLElement,
// Pointer events
const onPointerMove = (e: PointerEvent) => {
const onPointerMove = (e: PointerEvent): void => {
if (!e.buttons) viewportPointerInteractionOngoing = false;
const modifiers = makeModifiersBitfield(e);
editor.instance.on_mouse_move(e.clientX, e.clientY, e.buttons, modifiers);
};
const onPointerDown = (e: PointerEvent) => {
const onPointerDown = (e: PointerEvent): void => {
const { target } = e;
const inCanvas = target instanceof Element && target.closest(".canvas");
const inDialog = target instanceof Element && target.closest(".dialog-modal .floating-menu-content");
@@ -121,7 +122,7 @@ export function createInputManager(editor: EditorState, container: HTMLElement,
}
};
const onPointerUp = (e: PointerEvent) => {
const onPointerUp = (e: PointerEvent): void => {
if (!e.buttons) viewportPointerInteractionOngoing = false;
const modifiers = makeModifiersBitfield(e);
@@ -130,13 +131,13 @@ export function createInputManager(editor: EditorState, container: HTMLElement,
// Mouse events
const onMouseDown = (e: MouseEvent) => {
const onMouseDown = (e: MouseEvent): void => {
// Block middle mouse button auto-scroll mode (the circlar widget that appears and allows quick scrolling by moving the cursor above or below it)
// This has to be in `mousedown`, not `pointerdown`, to avoid blocking Vue's middle click detection on HTML elements
if (e.button === 1) e.preventDefault();
};
const onMouseScroll = (e: WheelEvent) => {
const onMouseScroll = (e: WheelEvent): void => {
const { target } = e;
const inCanvas = target instanceof Element && target.closest(".canvas");
@@ -155,7 +156,7 @@ export function createInputManager(editor: EditorState, container: HTMLElement,
// Window events
const onWindowResize = (container: HTMLElement) => {
const onWindowResize = (container: HTMLElement): void => {
const viewports = Array.from(container.querySelectorAll(".canvas"));
const boundsOfViewports = viewports.map((canvas) => {
const bounds = canvas.getBoundingClientRect();
@@ -168,7 +169,7 @@ export function createInputManager(editor: EditorState, container: HTMLElement,
if (boundsOfViewports.length > 0) editor.instance.bounds_of_viewports(data);
};
const onBeforeUnload = (e: BeforeUnloadEvent) => {
const onBeforeUnload = (e: BeforeUnloadEvent): void => {
const activeDocument = document.state.documents[document.state.activeDocumentIndex];
if (!activeDocument.is_saved) editor.instance.trigger_auto_save(activeDocument.id);
@@ -187,11 +188,11 @@ export function createInputManager(editor: EditorState, container: HTMLElement,
// Event bindings
const addListeners = () => {
const addListeners = (): void => {
listeners.forEach(({ target, eventName, action, options }) => target.addEventListener(eventName, action, options));
};
const removeListeners = () => {
const removeListeners = (): void => {
listeners.forEach(({ target, eventName, action }) => target.removeEventListener(eventName, action));
};