|
@@ -523,7 +523,7 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
523
|
523
|
collabForceLoadFlag,
|
524
|
524
|
);
|
525
|
525
|
// if loading same room as the one previously unloaded within 15sec
|
526
|
|
- // force reload without prompting
|
|
526
|
+ // force reload without prompting
|
527
|
527
|
if (previousRoom === roomID && Date.now() - timestamp < 15000) {
|
528
|
528
|
return true;
|
529
|
529
|
}
|
|
@@ -561,8 +561,8 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
561
|
561
|
history.clear();
|
562
|
562
|
};
|
563
|
563
|
|
564
|
|
- /** Completely resets scene & history.
|
565
|
|
- * Do not use for clear scene user action. */
|
|
564
|
+ // Completely resets scene & history.
|
|
565
|
+ // Do not use for clear scene user action.
|
566
|
566
|
private resetScene = withBatchedUpdates(() => {
|
567
|
567
|
this.scene.replaceAllElements([]);
|
568
|
568
|
this.setState({
|
|
@@ -654,7 +654,7 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
654
|
654
|
|
655
|
655
|
if (isCollaborationScene) {
|
656
|
656
|
// when joining a room we don't want user's local scene data to be merged
|
657
|
|
- // into the remote scene
|
|
657
|
+ // into the remote scene
|
658
|
658
|
this.resetScene();
|
659
|
659
|
|
660
|
660
|
this.initializeSocketClient({ showLoadingState: true });
|
|
@@ -847,7 +847,7 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
847
|
847
|
!isSavedToFirebase(this.portal, syncableElements)
|
848
|
848
|
) {
|
849
|
849
|
// this won't run in time if user decides to leave the site, but
|
850
|
|
- // the purpose is to run in immediately after user decides to stay
|
|
850
|
+ // the purpose is to run in immediately after user decides to stay
|
851
|
851
|
this.saveCollabRoomToFirebase(syncableElements);
|
852
|
852
|
|
853
|
853
|
event.preventDefault();
|
|
@@ -943,7 +943,7 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
943
|
943
|
const { atLeastOneVisibleElement, scrollBars } = renderScene(
|
944
|
944
|
elements.filter((element) => {
|
945
|
945
|
// don't render text element that's being currently edited (it's
|
946
|
|
- // rendered on remote only)
|
|
946
|
+ // rendered on remote only)
|
947
|
947
|
return (
|
948
|
948
|
!this.state.editingElement ||
|
949
|
949
|
this.state.editingElement.type !== "text" ||
|
|
@@ -1108,7 +1108,7 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
1108
|
1108
|
const elementUnderCursor = document.elementFromPoint(cursorX, cursorY);
|
1109
|
1109
|
if (
|
1110
|
1110
|
// if no ClipboardEvent supplied, assume we're pasting via contextMenu
|
1111
|
|
- // thus these checks don't make sense
|
|
1111
|
+ // thus these checks don't make sense
|
1112
|
1112
|
event &&
|
1113
|
1113
|
(!(elementUnderCursor instanceof HTMLCanvasElement) ||
|
1114
|
1114
|
isWritableElement(target))
|
|
@@ -1380,7 +1380,7 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
1380
|
1380
|
const roomKey = roomMatch[2];
|
1381
|
1381
|
|
1382
|
1382
|
// fallback in case you're not alone in the room but still don't receive
|
1383
|
|
- // initial SCENE_UPDATE message
|
|
1383
|
+ // initial SCENE_UPDATE message
|
1384
|
1384
|
this.socketInitializationTimer = setTimeout(
|
1385
|
1385
|
this.initializeSocket,
|
1386
|
1386
|
INITIAL_SCENE_UPDATE_TIMEOUT,
|
|
@@ -1432,7 +1432,7 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
1432
|
1432
|
decryptedData.payload.socketID;
|
1433
|
1433
|
|
1434
|
1434
|
// NOTE purposefully mutating collaborators map in case of
|
1435
|
|
- // pointer updates so as not to trigger LayerUI rerender
|
|
1435
|
+ // pointer updates so as not to trigger LayerUI rerender
|
1436
|
1436
|
this.setState((state) => {
|
1437
|
1437
|
if (!state.collaborators.has(socketId)) {
|
1438
|
1438
|
state.collaborators.set(socketId, {});
|
|
@@ -1467,9 +1467,9 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
1467
|
1467
|
if (elements) {
|
1468
|
1468
|
this.handleRemoteSceneUpdate(elements, { initFromSnapshot: true });
|
1469
|
1469
|
}
|
1470
|
|
- } catch (e) {
|
|
1470
|
+ } catch (error) {
|
1471
|
1471
|
// log the error and move on. other peers will sync us the scene.
|
1472
|
|
- console.error(e);
|
|
1472
|
+ console.error(error);
|
1473
|
1473
|
}
|
1474
|
1474
|
}
|
1475
|
1475
|
};
|
|
@@ -1814,7 +1814,7 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
1814
|
1814
|
});
|
1815
|
1815
|
|
1816
|
1816
|
// do an initial update to re-initialize element position since we were
|
1817
|
|
- // modifying element's x/y for sake of editor (case: syncing to remote)
|
|
1817
|
+ // modifying element's x/y for sake of editor (case: syncing to remote)
|
1818
|
1818
|
updateElement(element.text);
|
1819
|
1819
|
}
|
1820
|
1820
|
|
|
@@ -1920,7 +1920,7 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
1920
|
1920
|
|
1921
|
1921
|
if (existingTextElement) {
|
1922
|
1922
|
// if text element is no longer centered to a container, reset
|
1923
|
|
- // verticalAlign to default because it's currently internal-only
|
|
1923
|
+ // verticalAlign to default because it's currently internal-only
|
1924
|
1924
|
if (!parentCenterPosition || element.textAlign !== "center") {
|
1925
|
1925
|
mutateElement(element, { verticalAlign: DEFAULT_VERTICAL_ALIGN });
|
1926
|
1926
|
}
|
|
@@ -1931,7 +1931,7 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
1931
|
1931
|
]);
|
1932
|
1932
|
|
1933
|
1933
|
// case: creating new text not centered to parent elemenent → offset Y
|
1934
|
|
- // so that the text is centered to cursor position
|
|
1934
|
+ // so that the text is centered to cursor position
|
1935
|
1935
|
if (!parentCenterPosition) {
|
1936
|
1936
|
mutateElement(element, {
|
1937
|
1937
|
y: element.y - element.baseline / 2,
|
|
@@ -1952,7 +1952,7 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
1952
|
1952
|
event: React.MouseEvent<HTMLCanvasElement>,
|
1953
|
1953
|
) => {
|
1954
|
1954
|
// case: double-clicking with arrow/line tool selected would both create
|
1955
|
|
- // text and enter multiElement mode
|
|
1955
|
+ // text and enter multiElement mode
|
1956
|
1956
|
if (this.state.multiElement) {
|
1957
|
1957
|
return;
|
1958
|
1958
|
}
|
|
@@ -2129,7 +2129,7 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
2129
|
2129
|
|
2130
|
2130
|
if (lastPoint === lastCommittedPoint) {
|
2131
|
2131
|
// if we haven't yet created a temp point and we're beyond commit-zone
|
2132
|
|
- // threshold, add a point
|
|
2132
|
+ // threshold, add a point
|
2133
|
2133
|
if (
|
2134
|
2134
|
distance2d(
|
2135
|
2135
|
scenePointerX - rx,
|
|
@@ -2144,11 +2144,11 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
2144
|
2144
|
} else {
|
2145
|
2145
|
document.documentElement.style.cursor = CURSOR_TYPE.POINTER;
|
2146
|
2146
|
// in this branch, we're inside the commit zone, and no uncommitted
|
2147
|
|
- // point exists. Thus do nothing (don't add/remove points).
|
|
2147
|
+ // point exists. Thus do nothing (don't add/remove points).
|
2148
|
2148
|
}
|
2149
|
2149
|
} else {
|
2150
|
2150
|
// cursor moved inside commit zone, and there's uncommitted point,
|
2151
|
|
- // thus remove it
|
|
2151
|
+ // thus remove it
|
2152
|
2152
|
if (
|
2153
|
2153
|
points.length > 2 &&
|
2154
|
2154
|
lastCommittedPoint &&
|
|
@@ -2293,8 +2293,8 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
2293
|
2293
|
// fixes pointermove causing selection of UI texts #32
|
2294
|
2294
|
event.preventDefault();
|
2295
|
2295
|
// Preventing the event above disables default behavior
|
2296
|
|
- // of defocusing potentially focused element, which is what we
|
2297
|
|
- // want when clicking inside the canvas.
|
|
2296
|
+ // of defocusing potentially focused element, which is what we
|
|
2297
|
+ // want when clicking inside the canvas.
|
2298
|
2298
|
if (document.activeElement instanceof HTMLElement) {
|
2299
|
2299
|
document.activeElement.blur();
|
2300
|
2300
|
}
|
|
@@ -2739,8 +2739,8 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
2739
|
2739
|
}
|
2740
|
2740
|
|
2741
|
2741
|
// Add hit element to selection. At this point if we're not holding
|
2742
|
|
- // SHIFT the previously selected element(s) were deselected above
|
2743
|
|
- // (make sure you use setState updater to use latest state)
|
|
2742
|
+ // SHIFT the previously selected element(s) were deselected above
|
|
2743
|
+ // (make sure you use setState updater to use latest state)
|
2744
|
2744
|
if (
|
2745
|
2745
|
!someHitElementIsSelected &&
|
2746
|
2746
|
!pointerDownState.hit.hasHitCommonBoundingBoxOfSelectedElements
|
|
@@ -2798,8 +2798,8 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
2798
|
2798
|
pointerDownState: PointerDownState,
|
2799
|
2799
|
): void => {
|
2800
|
2800
|
// if we're currently still editing text, clicking outside
|
2801
|
|
- // should only finalize it, not create another (irrespective
|
2802
|
|
- // of state.elementLocked)
|
|
2801
|
+ // should only finalize it, not create another (irrespective
|
|
2802
|
+ // of state.elementLocked)
|
2803
|
2803
|
if (this.state.editingElement?.type === "text") {
|
2804
|
2804
|
return;
|
2805
|
2805
|
}
|
|
@@ -2860,7 +2860,7 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
2860
|
2860
|
},
|
2861
|
2861
|
}));
|
2862
|
2862
|
// clicking outside commit zone → update reference for last committed
|
2863
|
|
- // point
|
|
2863
|
+ // point
|
2864
|
2864
|
mutateElement(multiElement, {
|
2865
|
2865
|
lastCommittedPoint: multiElement.points[multiElement.points.length - 1],
|
2866
|
2866
|
});
|
|
@@ -2986,9 +2986,9 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
2986
|
2986
|
);
|
2987
|
2987
|
|
2988
|
2988
|
// for arrows/lines, don't start dragging until a given threshold
|
2989
|
|
- // to ensure we don't create a 2-point arrow by mistake when
|
2990
|
|
- // user clicks mouse in a way that it moves a tiny bit (thus
|
2991
|
|
- // triggering pointermove)
|
|
2989
|
+ // to ensure we don't create a 2-point arrow by mistake when
|
|
2990
|
+ // user clicks mouse in a way that it moves a tiny bit (thus
|
|
2991
|
+ // triggering pointermove)
|
2992
|
2992
|
if (
|
2993
|
2993
|
!pointerDownState.drag.hasOccurred &&
|
2994
|
2994
|
(this.state.elementType === "arrow" ||
|
|
@@ -3127,7 +3127,7 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
3127
|
3127
|
if (
|
3128
|
3128
|
this.state.selectedElementIds[element.id] ||
|
3129
|
3129
|
// case: the state.selectedElementIds might not have been
|
3130
|
|
- // updated yet by the time this mousemove event is fired
|
|
3130
|
+ // updated yet by the time this mousemove event is fired
|
3131
|
3131
|
(element.id === hitElement?.id &&
|
3132
|
3132
|
pointerDownState.hit.wasAddedToSelection)
|
3133
|
3133
|
) {
|
|
@@ -3331,7 +3331,7 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
3331
|
3331
|
selectionElement: null,
|
3332
|
3332
|
cursorButton: "up",
|
3333
|
3333
|
// text elements are reset on finalize, and resetting on pointerup
|
3334
|
|
- // may cause issues with double taps
|
|
3334
|
+ // may cause issues with double taps
|
3335
|
3335
|
editingElement:
|
3336
|
3336
|
multiElement || isTextElement(this.state.editingElement)
|
3337
|
3337
|
? this.state.editingElement
|
|
@@ -3481,8 +3481,8 @@ class App extends React.Component<ExcalidrawProps, AppState> {
|
3481
|
3481
|
if (this.state.selectedElementIds[hitElement.id]) {
|
3482
|
3482
|
if (isSelectedViaGroup(this.state, hitElement)) {
|
3483
|
3483
|
// We want to unselect all groups hitElement is part of
|
3484
|
|
- // as well as all elements that are part of the groups
|
3485
|
|
- // hitElement is part of
|
|
3484
|
+ // as well as all elements that are part of the groups
|
|
3485
|
+ // hitElement is part of
|
3486
|
3486
|
const idsOfSelectedElementsThatAreInGroups = hitElement.groupIds
|
3487
|
3487
|
.flatMap((groupId) =>
|
3488
|
3488
|
getElementsInGroup(this.scene.getElements(), groupId),
|