From f1ac8cac32cd77b5f6d57c50a374783753daa971 Mon Sep 17 00:00:00 2001 From: dwelle Date: Thu, 12 Mar 2020 19:40:04 +0100 Subject: [PATCH 1/2] remove unused selectedId --- src/data/index.ts | 4 +--- src/data/types.ts | 1 - src/types.ts | 1 - 3 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/data/index.ts b/src/data/index.ts index aea93bd0..9ec26e0f 100644 --- a/src/data/index.ts +++ b/src/data/index.ts @@ -341,12 +341,10 @@ export async function exportCanvas( export async function loadScene(id: string | null, privateKey?: string) { let data; - let selectedId; if (id != null) { // the private key is used to decrypt the content from the server, take // extra care not to leak it data = await importFromBackend(id, privateKey); - selectedId = id; window.history.replaceState({}, "Excalidraw", window.location.origin); } else { data = restoreFromLocalStorage(); @@ -354,6 +352,6 @@ export async function loadScene(id: string | null, privateKey?: string) { return { elements: data.elements, - appState: data.appState && { ...data.appState, selectedId }, + appState: data.appState && { ...data.appState }, }; } diff --git a/src/data/types.ts b/src/data/types.ts index daa85c6f..7d0166cc 100644 --- a/src/data/types.ts +++ b/src/data/types.ts @@ -7,5 +7,4 @@ export interface DataState { source?: string; elements: readonly ExcalidrawElement[]; appState: AppState | null; - selectedId?: number; } diff --git a/src/types.ts b/src/types.ts index 457d806f..9c81150c 100644 --- a/src/types.ts +++ b/src/types.ts @@ -28,7 +28,6 @@ export type AppState = { cursorY: number; scrolledOutside: boolean; name: string; - selectedId?: string; isCollaborating: boolean; isResizing: boolean; zoom: number; From c04fe403fccbd37472ad0fc2f19f1905f2dcfc3b Mon Sep 17 00:00:00 2001 From: dwelle Date: Thu, 12 Mar 2020 21:28:58 +0100 Subject: [PATCH 2/2] don't sync editing elements & prefer local versions --- src/components/App.tsx | 68 +++++++++++++++++++++++++++++++++--------- 1 file changed, 54 insertions(+), 14 deletions(-) diff --git a/src/components/App.tsx b/src/components/App.tsx index c25962dc..44fd4ea3 100644 --- a/src/components/App.tsx +++ b/src/components/App.tsx @@ -293,7 +293,7 @@ export class App extends React.Component { } else { // create a map of ids so we don't have to iterate // over the array more than once. - const elementMap = elements.reduce( + const localElementMap = elements.reduce( ( acc: { [key: string]: ExcalidrawElement }, element: ExcalidrawElement, @@ -304,15 +304,42 @@ export class App extends React.Component { {}, ); // Reconcile - elements = restoredState.elements.map(element => { - if ( - elementMap.hasOwnProperty(element.id) && - elementMap[element.id].version > element.version - ) { - return elementMap[element.id]; - } - return element; - }); + elements = restoredState.elements + .reduce((elements, element) => { + // if the remote element references one that's currently + // edited on local, skip it (it'll be added in the next + // step) + if ( + element.id === this.state.editingElement?.id || + element.id === this.state.resizingElement?.id || + element.id === this.state.draggingElement?.id + ) { + return elements; + } + + if ( + localElementMap.hasOwnProperty(element.id) && + localElementMap[element.id].version > element.version + ) { + elements.push(localElementMap[element.id]); + } else { + elements.push(element); + } + + return elements; + }, [] as any) + // add local elements that are currently being edited + // (can't be done in the step above because the elements may + // not exist on remote at all) + .concat( + elements.filter(element => { + return ( + element.id === this.state.editingElement?.id || + element.id === this.state.resizingElement?.id || + element.id === this.state.draggingElement?.id + ); + }), + ); } this.setState({}); if (this.socketInitialized === false) { @@ -344,7 +371,9 @@ export class App extends React.Component { this.broadcastSocketData({ type: "SCENE_UPDATE", payload: { - elements, + elements: elements.filter(element => { + return element.id !== this.state.editingElement?.id; + }), appState: this.state, }, }); @@ -1368,6 +1397,7 @@ export class App extends React.Component { elements = [...elements, element]; this.setState({ draggingElement: element, + editingElement: element, }); } } else if (element.type === "selection") { @@ -1377,7 +1407,11 @@ export class App extends React.Component { }); } else { elements = [...elements, element]; - this.setState({ multiElement: null, draggingElement: element }); + this.setState({ + multiElement: null, + draggingElement: element, + editingElement: element, + }); } let resizeArrowFn: @@ -1846,6 +1880,7 @@ export class App extends React.Component { isResizing: false, resizingElement: null, selectionElement: null, + editingElement: multiElement ? this.state.editingElement : null, }); resizeArrowFn = null; @@ -1869,7 +1904,10 @@ export class App extends React.Component { y - draggingElement.y, ]); invalidateShapeForElement(draggingElement); - this.setState({ multiElement: this.state.draggingElement }); + this.setState({ + multiElement: this.state.draggingElement, + editingElement: this.state.draggingElement, + }); } else if (draggingOccurred && !multiElement) { if (!elementLocked) { resetCursor(); @@ -2135,7 +2173,9 @@ export class App extends React.Component { this.broadcastSocketData({ type: "SCENE_UPDATE", payload: { - elements, + elements: elements.filter(element => { + return element.id !== this.state.editingElement?.id; + }), appState: this.state, }, });