Save scene in URL (#220)

Co-authored-by: Christopher Chedeau <vjeuxx@gmail.com>
This commit is contained in:
Timur Khazamov 2020-01-07 08:08:23 +05:00 committed by Christopher Chedeau
parent abbc04df0e
commit db973c61e8
3 changed files with 40 additions and 3 deletions

View File

@ -25,6 +25,8 @@ import {
exportAsPNG, exportAsPNG,
restoreFromLocalStorage, restoreFromLocalStorage,
saveToLocalStorage, saveToLocalStorage,
restoreFromURL,
saveToURL,
hasBackground, hasBackground,
hasStroke, hasStroke,
getElementAtPosition, getElementAtPosition,
@ -122,7 +124,8 @@ class App extends React.Component<{}, AppState> {
document.addEventListener("keydown", this.onKeyDown, false); document.addEventListener("keydown", this.onKeyDown, false);
window.addEventListener("resize", this.onResize, false); window.addEventListener("resize", this.onResize, false);
const savedState = restoreFromLocalStorage(elements); const savedState =
restoreFromURL(elements) || restoreFromLocalStorage(elements);
if (savedState) { if (savedState) {
this.setState(savedState); this.setState(savedState);
} }
@ -997,6 +1000,11 @@ class App extends React.Component<{}, AppState> {
})); }));
}; };
private saveDebounced = debounce(() => {
saveToLocalStorage(elements, this.state);
saveToURL(elements, this.state);
}, 300);
private addElementsFromPaste = (paste: string, x?: number, y?: number) => { private addElementsFromPaste = (paste: string, x?: number, y?: number) => {
let parsedElements; let parsedElements;
try { try {
@ -1037,7 +1045,7 @@ class App extends React.Component<{}, AppState> {
scrollY: this.state.scrollY, scrollY: this.state.scrollY,
viewBackgroundColor: this.state.viewBackgroundColor viewBackgroundColor: this.state.viewBackgroundColor
}); });
saveToLocalStorage(elements, this.state); this.saveDebounced();
if (history.isRecording()) { if (history.isRecording()) {
history.pushEntry(history.generateCurrentEntry(elements)); history.pushEntry(history.generateCurrentEntry(elements));
history.clearRedoStack(); history.clearRedoStack();
@ -1046,6 +1054,14 @@ class App extends React.Component<{}, AppState> {
} }
} }
function debounce<T extends any[]>(fn: (...args: T) => void, timeout: number) {
let handle = 0;
return (...args: T) => {
clearTimeout(handle);
handle = window.setTimeout(() => fn(...args), timeout);
};
}
const rootElement = document.getElementById("root"); const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement); ReactDOM.render(<App />, rootElement);
const canvas = document.getElementById("canvas") as HTMLCanvasElement; const canvas = document.getElementById("canvas") as HTMLCanvasElement;

View File

@ -181,3 +181,22 @@ export function saveToLocalStorage(
localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(elements)); localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(elements));
localStorage.setItem(LOCAL_STORAGE_KEY_STATE, JSON.stringify(state)); localStorage.setItem(LOCAL_STORAGE_KEY_STATE, JSON.stringify(state));
} }
export function restoreFromURL(elements: ExcalidrawElement[]) {
try {
const [savedElements, savedState] = document.location.hash
.slice(1)
.split(":")
.map(atob);
return restore(elements, savedElements, savedState);
} catch (ex) {
return null;
}
}
export function saveToURL(elements: ExcalidrawElement[], state: AppState) {
const hash = [JSON.stringify(elements), JSON.stringify(state)]
.map(btoa)
.join(":");
document.location.replace("#" + hash);
}

View File

@ -13,7 +13,9 @@ export {
loadFromJSON, loadFromJSON,
saveAsJSON, saveAsJSON,
restoreFromLocalStorage, restoreFromLocalStorage,
saveToLocalStorage saveToLocalStorage,
restoreFromURL,
saveToURL
} from "./data"; } from "./data";
export { hasBackground, hasStroke, getElementAtPosition } from "./comparisons"; export { hasBackground, hasStroke, getElementAtPosition } from "./comparisons";
export { createScene } from "./createScene"; export { createScene } from "./createScene";