diff --git a/src/index.tsx b/src/index.tsx index f595e5433..d6295d9c7 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -106,10 +106,16 @@ export class App extends React.Component<{}, AppState> { document.addEventListener("keydown", this.onKeyDown, false); window.addEventListener("resize", this.onResize, false); - const appState = restoreFromLocalStorage(elements); + const { elements: newElements, appState } = restoreFromLocalStorage(); + + if (newElements) { + elements = newElements; + } if (appState) { this.setState(appState); + } else { + this.forceUpdate(); } } @@ -512,7 +518,10 @@ export class App extends React.Component<{}, AppState> { } onSaveScene={() => saveAsJSON(elements, this.state.name)} onLoadScene={() => - loadFromJSON(elements).then(() => this.forceUpdate()) + loadFromJSON().then(({ elements: newElements }) => { + elements = newElements; + this.forceUpdate(); + }) } /> diff --git a/src/scene/data.ts b/src/scene/data.ts index bfcaf4903..89993358d 100644 --- a/src/scene/data.ts +++ b/src/scene/data.ts @@ -22,6 +22,11 @@ function saveFile(name: string, data: string) { link.remove(); } +interface DataState { + elements: ExcalidrawElement[]; + appState: any; +} + export function saveAsJSON(elements: ExcalidrawElement[], name: string) { const serialized = JSON.stringify({ version: 1, @@ -35,7 +40,7 @@ export function saveAsJSON(elements: ExcalidrawElement[], name: string) { ); } -export function loadFromJSON(elements: ExcalidrawElement[]) { +export function loadFromJSON() { const input = document.createElement("input"); const reader = new FileReader(); input.type = "file"; @@ -52,12 +57,17 @@ export function loadFromJSON(elements: ExcalidrawElement[]) { input.click(); - return new Promise(resolve => { + return new Promise(resolve => { reader.onloadend = () => { if (reader.readyState === FileReader.DONE) { - const data = JSON.parse(reader.result as string); - restore(elements, data.elements, null); - resolve(); + let elements = []; + try { + const data = JSON.parse(reader.result as string); + elements = data.elements || []; + } catch (e) { + // Do nothing because elements array is already empty + } + resolve(restore(elements, null)); } }; }); @@ -130,43 +140,48 @@ export function exportAsPNG( } function restore( - elements: ExcalidrawElement[], - savedElements: string | ExcalidrawElement[] | null, - savedState: string | null -) { - try { - if (savedElements) { - elements.splice( - 0, - elements.length, - ...(typeof savedElements === "string" - ? JSON.parse(savedElements) - : savedElements) - ); - elements.forEach((element: ExcalidrawElement) => { - element.id = element.id || nanoid(); - element.fillStyle = element.fillStyle || "hachure"; - element.strokeWidth = element.strokeWidth || 1; - element.roughness = element.roughness || 1; - element.opacity = - element.opacity === null || element.opacity === undefined - ? 100 - : element.opacity; - }); - } - - return savedState ? JSON.parse(savedState) : null; - } catch (e) { - elements.splice(0, elements.length); - return null; - } + savedElements: ExcalidrawElement[], + savedState: any +): DataState { + return { + elements: savedElements.map(element => ({ + ...element, + id: element.id || nanoid(), + fillStyle: element.fillStyle || "hachure", + strokeWidth: element.strokeWidth || 1, + roughness: element.roughness || 1, + opacity: + element.opacity === null || element.opacity === undefined + ? 100 + : element.opacity + })), + appState: savedState + }; } -export function restoreFromLocalStorage(elements: ExcalidrawElement[]) { +export function restoreFromLocalStorage() { const savedElements = localStorage.getItem(LOCAL_STORAGE_KEY); const savedState = localStorage.getItem(LOCAL_STORAGE_KEY_STATE); - return restore(elements, savedElements, savedState); + let elements = []; + if (savedElements) { + try { + elements = JSON.parse(savedElements); + } catch (e) { + // Do nothing because elements array is already empty + } + } + + let appState = null; + if (savedState) { + try { + appState = JSON.parse(savedState); + } catch (e) { + // Do nothing because appState is already null + } + } + + return restore(elements, appState); } export function saveToLocalStorage(