refactor(app.tsx): use constants instead of hard coded strings for better readablility (#1391)
don't use inline function as it will create a new refrence everytime
This commit is contained in:
parent
d902bbd618
commit
e98fba38be
@ -95,6 +95,7 @@ import {
|
|||||||
import { normalizeScroll } from "../scene";
|
import { normalizeScroll } from "../scene";
|
||||||
import { getCenter, getDistance } from "../gesture";
|
import { getCenter, getDistance } from "../gesture";
|
||||||
import { createUndoAction, createRedoAction } from "../actions/actionHistory";
|
import { createUndoAction, createRedoAction } from "../actions/actionHistory";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
CURSOR_TYPE,
|
CURSOR_TYPE,
|
||||||
ELEMENT_SHIFT_TRANSLATE_AMOUNT,
|
ELEMENT_SHIFT_TRANSLATE_AMOUNT,
|
||||||
@ -103,7 +104,16 @@ import {
|
|||||||
DRAGGING_THRESHOLD,
|
DRAGGING_THRESHOLD,
|
||||||
TEXT_TO_CENTER_SNAP_THRESHOLD,
|
TEXT_TO_CENTER_SNAP_THRESHOLD,
|
||||||
LINE_CONFIRM_THRESHOLD,
|
LINE_CONFIRM_THRESHOLD,
|
||||||
|
SCENE,
|
||||||
|
EVENT,
|
||||||
|
ENV,
|
||||||
} from "../constants";
|
} from "../constants";
|
||||||
|
import {
|
||||||
|
FONT_LOAD_THRESHOLD,
|
||||||
|
INITAL_SCENE_UPDATE_TIMEOUT,
|
||||||
|
TAP_TWICE_TIMEOUT,
|
||||||
|
} from "../time_constants";
|
||||||
|
|
||||||
import { LayerUI } from "./LayerUI";
|
import { LayerUI } from "./LayerUI";
|
||||||
import { ScrollBars, SceneState } from "../scene/types";
|
import { ScrollBars, SceneState } from "../scene/types";
|
||||||
import { generateCollaborationLink, getCollaborationLinkData } from "../data";
|
import { generateCollaborationLink, getCollaborationLinkData } from "../data";
|
||||||
@ -363,7 +373,7 @@ export class App extends React.Component<any, AppState> {
|
|||||||
});
|
});
|
||||||
}),
|
}),
|
||||||
// if fonts don't load in 1s for whatever reason, don't block the UI
|
// if fonts don't load in 1s for whatever reason, don't block the UI
|
||||||
new Promise((resolve) => setTimeout(resolve, 1000)),
|
new Promise((resolve) => setTimeout(resolve, FONT_LOAD_THRESHOLD)),
|
||||||
]);
|
]);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
@ -411,32 +421,39 @@ export class App extends React.Component<any, AppState> {
|
|||||||
this.onSceneUpdated,
|
this.onSceneUpdated,
|
||||||
);
|
);
|
||||||
|
|
||||||
document.addEventListener("copy", this.onCopy);
|
document.addEventListener(EVENT.COPY, this.onCopy);
|
||||||
document.addEventListener("paste", this.pasteFromClipboard);
|
document.addEventListener(EVENT.PASTE, this.pasteFromClipboard);
|
||||||
document.addEventListener("cut", this.onCut);
|
document.addEventListener(EVENT.CUT, this.onCut);
|
||||||
|
|
||||||
document.addEventListener("keydown", this.onKeyDown, false);
|
document.addEventListener(EVENT.KEYDOWN, this.onKeyDown, false);
|
||||||
document.addEventListener("keyup", this.onKeyUp, { passive: true });
|
document.addEventListener(EVENT.KEYUP, this.onKeyUp, { passive: true });
|
||||||
document.addEventListener("mousemove", this.updateCurrentCursorPosition);
|
document.addEventListener(
|
||||||
window.addEventListener("resize", this.onResize, false);
|
EVENT.MOUSE_MOVE,
|
||||||
window.addEventListener("unload", this.onUnload, false);
|
this.updateCurrentCursorPosition,
|
||||||
window.addEventListener("blur", this.onBlur, false);
|
);
|
||||||
window.addEventListener("dragover", this.disableEvent, false);
|
window.addEventListener(EVENT.RESIZE, this.onResize, false);
|
||||||
window.addEventListener("drop", this.disableEvent, false);
|
window.addEventListener(EVENT.UNLOAD, this.onUnload, false);
|
||||||
|
window.addEventListener(EVENT.BLUR, this.onBlur, false);
|
||||||
|
window.addEventListener(EVENT.DRAG_OVER, this.disableEvent, false);
|
||||||
|
window.addEventListener(EVENT.DROP, this.disableEvent, false);
|
||||||
|
|
||||||
// Safari-only desktop pinch zoom
|
// Safari-only desktop pinch zoom
|
||||||
document.addEventListener(
|
document.addEventListener(
|
||||||
"gesturestart",
|
EVENT.GESTURE_START,
|
||||||
this.onGestureStart as any,
|
this.onGestureStart as any,
|
||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
document.addEventListener(
|
document.addEventListener(
|
||||||
"gesturechange",
|
EVENT.GESTURE_CHANGE,
|
||||||
this.onGestureChange as any,
|
this.onGestureChange as any,
|
||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
document.addEventListener("gestureend", this.onGestureEnd as any, false);
|
document.addEventListener(
|
||||||
window.addEventListener("beforeunload", this.beforeUnload);
|
EVENT.GESTURE_END,
|
||||||
|
this.onGestureEnd as any,
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
window.addEventListener(EVENT.BEFORE_UNLOAD, this.beforeUnload);
|
||||||
|
|
||||||
this.initializeScene();
|
this.initializeScene();
|
||||||
}
|
}
|
||||||
@ -445,35 +462,39 @@ export class App extends React.Component<any, AppState> {
|
|||||||
this.unmounted = true;
|
this.unmounted = true;
|
||||||
this.removeSceneCallback!();
|
this.removeSceneCallback!();
|
||||||
|
|
||||||
document.removeEventListener("copy", this.onCopy);
|
document.removeEventListener(EVENT.COPY, this.onCopy);
|
||||||
document.removeEventListener("paste", this.pasteFromClipboard);
|
document.removeEventListener(EVENT.PASTE, this.pasteFromClipboard);
|
||||||
document.removeEventListener("cut", this.onCut);
|
document.removeEventListener(EVENT.CUT, this.onCut);
|
||||||
|
|
||||||
document.removeEventListener("keydown", this.onKeyDown, false);
|
document.removeEventListener(EVENT.KEYDOWN, this.onKeyDown, false);
|
||||||
document.removeEventListener(
|
document.removeEventListener(
|
||||||
"mousemove",
|
EVENT.MOUSE_MOVE,
|
||||||
this.updateCurrentCursorPosition,
|
this.updateCurrentCursorPosition,
|
||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
document.removeEventListener("keyup", this.onKeyUp);
|
document.removeEventListener(EVENT.KEYUP, this.onKeyUp);
|
||||||
window.removeEventListener("resize", this.onResize, false);
|
window.removeEventListener(EVENT.RESIZE, this.onResize, false);
|
||||||
window.removeEventListener("unload", this.onUnload, false);
|
window.removeEventListener(EVENT.UNLOAD, this.onUnload, false);
|
||||||
window.removeEventListener("blur", this.onBlur, false);
|
window.removeEventListener(EVENT.BLUR, this.onBlur, false);
|
||||||
window.removeEventListener("dragover", this.disableEvent, false);
|
window.removeEventListener(EVENT.DRAG_OVER, this.disableEvent, false);
|
||||||
window.removeEventListener("drop", this.disableEvent, false);
|
window.removeEventListener(EVENT.DROP, this.disableEvent, false);
|
||||||
|
|
||||||
document.removeEventListener(
|
document.removeEventListener(
|
||||||
"gesturestart",
|
EVENT.GESTURE_START,
|
||||||
this.onGestureStart as any,
|
this.onGestureStart as any,
|
||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
document.removeEventListener(
|
document.removeEventListener(
|
||||||
"gesturechange",
|
EVENT.GESTURE_CHANGE,
|
||||||
this.onGestureChange as any,
|
this.onGestureChange as any,
|
||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
document.removeEventListener("gestureend", this.onGestureEnd as any, false);
|
document.removeEventListener(
|
||||||
window.removeEventListener("beforeunload", this.beforeUnload);
|
EVENT.GESTURE_END,
|
||||||
|
this.onGestureEnd as any,
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
window.removeEventListener(EVENT.BEFORE_UNLOAD, this.beforeUnload);
|
||||||
}
|
}
|
||||||
private onResize = withBatchedUpdates(() => {
|
private onResize = withBatchedUpdates(() => {
|
||||||
globalSceneState
|
globalSceneState
|
||||||
@ -574,7 +595,7 @@ export class App extends React.Component<any, AppState> {
|
|||||||
getDrawingVersion(globalSceneState.getElementsIncludingDeleted()) >
|
getDrawingVersion(globalSceneState.getElementsIncludingDeleted()) >
|
||||||
this.lastBroadcastedOrReceivedSceneVersion
|
this.lastBroadcastedOrReceivedSceneVersion
|
||||||
) {
|
) {
|
||||||
this.broadcastScene("SCENE_UPDATE");
|
this.broadcastScene(SCENE.UPDATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
history.record(this.state, globalSceneState.getElementsIncludingDeleted());
|
history.record(this.state, globalSceneState.getElementsIncludingDeleted());
|
||||||
@ -638,11 +659,18 @@ export class App extends React.Component<any, AppState> {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private resetTapTwice() {
|
||||||
|
didTapTwice = false;
|
||||||
|
}
|
||||||
|
|
||||||
private onTapStart = (event: TouchEvent) => {
|
private onTapStart = (event: TouchEvent) => {
|
||||||
if (!didTapTwice) {
|
if (!didTapTwice) {
|
||||||
didTapTwice = true;
|
didTapTwice = true;
|
||||||
clearTimeout(tappedTwiceTimer);
|
clearTimeout(tappedTwiceTimer);
|
||||||
tappedTwiceTimer = window.setTimeout(() => (didTapTwice = false), 300);
|
tappedTwiceTimer = window.setTimeout(
|
||||||
|
this.resetTapTwice,
|
||||||
|
TAP_TWICE_TIMEOUT,
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// insert text only if we tapped twice with a single finger
|
// insert text only if we tapped twice with a single finger
|
||||||
@ -809,10 +837,13 @@ export class App extends React.Component<any, AppState> {
|
|||||||
};
|
};
|
||||||
// fallback in case you're not alone in the room but still don't receive
|
// fallback in case you're not alone in the room but still don't receive
|
||||||
// initial SCENE_UPDATE message
|
// initial SCENE_UPDATE message
|
||||||
const initializationTimer = setTimeout(initialize, 5000);
|
const initializationTimer = setTimeout(
|
||||||
|
initialize,
|
||||||
|
INITAL_SCENE_UPDATE_TIMEOUT,
|
||||||
|
);
|
||||||
|
|
||||||
const updateScene = (
|
const updateScene = (
|
||||||
decryptedData: SocketUpdateDataSource["SCENE_INIT" | "SCENE_UPDATE"],
|
decryptedData: SocketUpdateDataSource[SCENE.INIT | SCENE.UPDATE],
|
||||||
{ scrollToContent = false }: { scrollToContent?: boolean } = {},
|
{ scrollToContent = false }: { scrollToContent?: boolean } = {},
|
||||||
) => {
|
) => {
|
||||||
const { elements: remoteElements } = decryptedData.payload;
|
const { elements: remoteElements } = decryptedData.payload;
|
||||||
@ -821,7 +852,7 @@ export class App extends React.Component<any, AppState> {
|
|||||||
this.setState({
|
this.setState({
|
||||||
...this.state,
|
...this.state,
|
||||||
...calculateScrollCenter(
|
...calculateScrollCenter(
|
||||||
remoteElements.filter((element) => {
|
remoteElements.filter((element: { isDeleted: boolean }) => {
|
||||||
return !element.isDeleted;
|
return !element.isDeleted;
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
@ -946,13 +977,13 @@ export class App extends React.Component<any, AppState> {
|
|||||||
switch (decryptedData.type) {
|
switch (decryptedData.type) {
|
||||||
case "INVALID_RESPONSE":
|
case "INVALID_RESPONSE":
|
||||||
return;
|
return;
|
||||||
case "SCENE_INIT": {
|
case SCENE.INIT: {
|
||||||
if (!this.portal.socketInitialized) {
|
if (!this.portal.socketInitialized) {
|
||||||
updateScene(decryptedData, { scrollToContent: true });
|
updateScene(decryptedData, { scrollToContent: true });
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "SCENE_UPDATE":
|
case SCENE.UPDATE:
|
||||||
updateScene(decryptedData);
|
updateScene(decryptedData);
|
||||||
break;
|
break;
|
||||||
case "MOUSE_LOCATION": {
|
case "MOUSE_LOCATION": {
|
||||||
@ -1003,7 +1034,7 @@ export class App extends React.Component<any, AppState> {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
this.portal.socket!.on("new-user", async (_socketID: string) => {
|
this.portal.socket!.on("new-user", async (_socketID: string) => {
|
||||||
this.broadcastScene("SCENE_INIT");
|
this.broadcastScene(SCENE.INIT);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
@ -1035,7 +1066,7 @@ export class App extends React.Component<any, AppState> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private broadcastScene = (sceneType: "SCENE_INIT" | "SCENE_UPDATE") => {
|
private broadcastScene = (sceneType: SCENE.INIT | SCENE.UPDATE) => {
|
||||||
const data: SocketUpdateDataSource[typeof sceneType] = {
|
const data: SocketUpdateDataSource[typeof sceneType] = {
|
||||||
type: sceneType,
|
type: sceneType,
|
||||||
payload: {
|
payload: {
|
||||||
@ -1651,16 +1682,16 @@ export class App extends React.Component<any, AppState> {
|
|||||||
cursorButton: "up",
|
cursorButton: "up",
|
||||||
});
|
});
|
||||||
this.savePointer(event.clientX, event.clientY, "up");
|
this.savePointer(event.clientX, event.clientY, "up");
|
||||||
window.removeEventListener("pointermove", onPointerMove);
|
window.removeEventListener(EVENT.POINTER_MOVE, onPointerMove);
|
||||||
window.removeEventListener("pointerup", teardown);
|
window.removeEventListener(EVENT.POINTER_UP, teardown);
|
||||||
window.removeEventListener("blur", teardown);
|
window.removeEventListener(EVENT.BLUR, teardown);
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
window.addEventListener("blur", teardown);
|
window.addEventListener(EVENT.BLUR, teardown);
|
||||||
window.addEventListener("pointermove", onPointerMove, {
|
window.addEventListener(EVENT.POINTER_MOVE, onPointerMove, {
|
||||||
passive: true,
|
passive: true,
|
||||||
});
|
});
|
||||||
window.addEventListener("pointerup", teardown);
|
window.addEventListener(EVENT.POINTER_UP, teardown);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1755,14 +1786,14 @@ export class App extends React.Component<any, AppState> {
|
|||||||
cursorButton: "up",
|
cursorButton: "up",
|
||||||
});
|
});
|
||||||
this.savePointer(event.clientX, event.clientY, "up");
|
this.savePointer(event.clientX, event.clientY, "up");
|
||||||
window.removeEventListener("pointermove", onPointerMove);
|
window.removeEventListener(EVENT.POINTER_MOVE, onPointerMove);
|
||||||
window.removeEventListener("pointerup", onPointerUp);
|
window.removeEventListener(EVENT.POINTER_UP, onPointerUp);
|
||||||
});
|
});
|
||||||
|
|
||||||
lastPointerUp = onPointerUp;
|
lastPointerUp = onPointerUp;
|
||||||
|
|
||||||
window.addEventListener("pointermove", onPointerMove);
|
window.addEventListener(EVENT.POINTER_MOVE, onPointerMove);
|
||||||
window.addEventListener("pointerup", onPointerUp);
|
window.addEventListener(EVENT.POINTER_UP, onPointerUp);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2230,8 +2261,8 @@ export class App extends React.Component<any, AppState> {
|
|||||||
resizeArrowFn = null;
|
resizeArrowFn = null;
|
||||||
lastPointerUp = null;
|
lastPointerUp = null;
|
||||||
|
|
||||||
window.removeEventListener("pointermove", onPointerMove);
|
window.removeEventListener(EVENT.POINTER_MOVE, onPointerMove);
|
||||||
window.removeEventListener("pointerup", onPointerUp);
|
window.removeEventListener(EVENT.POINTER_UP, onPointerUp);
|
||||||
|
|
||||||
if (isLinearElement(draggingElement)) {
|
if (isLinearElement(draggingElement)) {
|
||||||
if (draggingElement!.points.length > 1) {
|
if (draggingElement!.points.length > 1) {
|
||||||
@ -2367,8 +2398,8 @@ export class App extends React.Component<any, AppState> {
|
|||||||
|
|
||||||
lastPointerUp = onPointerUp;
|
lastPointerUp = onPointerUp;
|
||||||
|
|
||||||
window.addEventListener("pointermove", onPointerMove);
|
window.addEventListener(EVENT.POINTER_MOVE, onPointerMove);
|
||||||
window.addEventListener("pointerup", onPointerUp);
|
window.addEventListener(EVENT.POINTER_UP, onPointerUp);
|
||||||
};
|
};
|
||||||
|
|
||||||
private handleCanvasRef = (canvas: HTMLCanvasElement) => {
|
private handleCanvasRef = (canvas: HTMLCanvasElement) => {
|
||||||
@ -2377,13 +2408,13 @@ export class App extends React.Component<any, AppState> {
|
|||||||
this.canvas = canvas;
|
this.canvas = canvas;
|
||||||
this.rc = rough.canvas(this.canvas);
|
this.rc = rough.canvas(this.canvas);
|
||||||
|
|
||||||
this.canvas.addEventListener("wheel", this.handleWheel, {
|
this.canvas.addEventListener(EVENT.WHEEL, this.handleWheel, {
|
||||||
passive: false,
|
passive: false,
|
||||||
});
|
});
|
||||||
this.canvas.addEventListener("touchstart", this.onTapStart);
|
this.canvas.addEventListener(EVENT.TOUCH_START, this.onTapStart);
|
||||||
} else {
|
} else {
|
||||||
this.canvas?.removeEventListener("wheel", this.handleWheel);
|
this.canvas?.removeEventListener(EVENT.WHEEL, this.handleWheel);
|
||||||
this.canvas?.removeEventListener("touchstart", this.onTapStart);
|
this.canvas?.removeEventListener(EVENT.TOUCH_START, this.onTapStart);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -2610,7 +2641,10 @@ declare global {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (process.env.NODE_ENV === "test" || process.env.NODE_ENV === "development") {
|
if (
|
||||||
|
process.env.NODE_ENV === ENV.TEST ||
|
||||||
|
process.env.NODE_ENV === ENV.DEVELOPMENT
|
||||||
|
) {
|
||||||
window.h = {} as Window["h"];
|
window.h = {} as Window["h"];
|
||||||
|
|
||||||
Object.defineProperties(window.h, {
|
Object.defineProperties(window.h, {
|
||||||
|
@ -16,3 +16,35 @@ export const POINTER_BUTTON = {
|
|||||||
SECONDARY: 2,
|
SECONDARY: 2,
|
||||||
TOUCH: -1,
|
TOUCH: -1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export enum SCENE {
|
||||||
|
INIT = "SCENE_INIT",
|
||||||
|
UPDATE = "SCENE_UPDATE",
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum EVENT {
|
||||||
|
COPY = "copy",
|
||||||
|
PASTE = "paste",
|
||||||
|
CUT = "cut",
|
||||||
|
KEYDOWN = "keydown",
|
||||||
|
KEYUP = "keyup",
|
||||||
|
MOUSE_MOVE = "mousemove",
|
||||||
|
RESIZE = "resize",
|
||||||
|
UNLOAD = "unload",
|
||||||
|
BLUR = "blur",
|
||||||
|
DRAG_OVER = "dragover",
|
||||||
|
DROP = "drop",
|
||||||
|
GESTURE_END = "gestureend",
|
||||||
|
BEFORE_UNLOAD = "beforeunload",
|
||||||
|
GESTURE_START = "gesturestart",
|
||||||
|
GESTURE_CHANGE = "gesturechange",
|
||||||
|
POINTER_MOVE = "pointermove",
|
||||||
|
POINTER_UP = "pointerup",
|
||||||
|
WHEEL = "wheel",
|
||||||
|
TOUCH_START = "touchstart",
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ENV = {
|
||||||
|
TEST: "test",
|
||||||
|
DEVELOPMENT: "development",
|
||||||
|
};
|
||||||
|
4
src/time_constants.ts
Normal file
4
src/time_constants.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
// time in milliseconds
|
||||||
|
export const FONT_LOAD_THRESHOLD = 1000;
|
||||||
|
export const TAP_TWICE_TIMEOUT = 300;
|
||||||
|
export const INITAL_SCENE_UPDATE_TIMEOUT = 5000;
|
Loading…
x
Reference in New Issue
Block a user