Cmd-Z (#141)
This commit is contained in:
parent
4ca8f65887
commit
9e5c5daf64
@ -20,6 +20,34 @@ const LOCAL_STORAGE_KEY_STATE = "excalidraw-state";
|
||||
|
||||
const elements = Array.of<ExcalidrawElement>();
|
||||
|
||||
let skipHistory = false;
|
||||
const stateHistory: string[] = [];
|
||||
function generateHistoryCurrentEntry() {
|
||||
return JSON.stringify(
|
||||
elements.map(element => ({ ...element, isSelected: false }))
|
||||
);
|
||||
}
|
||||
function pushHistoryEntry(newEntry: string) {
|
||||
if (
|
||||
stateHistory.length > 0 &&
|
||||
stateHistory[stateHistory.length - 1] === newEntry
|
||||
) {
|
||||
// If the last entry is the same as this one, ignore it
|
||||
return;
|
||||
}
|
||||
stateHistory.push(newEntry);
|
||||
}
|
||||
function restoreHistoryEntry(entry: string) {
|
||||
const newElements = JSON.parse(entry);
|
||||
elements.splice(0, elements.length);
|
||||
newElements.forEach((newElement: ExcalidrawElement) => {
|
||||
generateDraw(newElement);
|
||||
elements.push(newElement);
|
||||
});
|
||||
// When restoring, we shouldn't add an history entry otherwise we'll be stuck with it and can't go back
|
||||
skipHistory = true;
|
||||
}
|
||||
|
||||
// https://stackoverflow.com/questions/521295/seeding-the-random-number-generator-in-javascript/47593316#47593316
|
||||
const LCG = (seed: number) => () =>
|
||||
((2 ** 31 - 1) & (seed = Math.imul(48271, seed))) / 2 ** 31;
|
||||
@ -901,6 +929,17 @@ class App extends React.Component<{}, AppState> {
|
||||
event.preventDefault();
|
||||
} else if (shapesShortcutKeys.includes(event.key.toLowerCase())) {
|
||||
this.setState({ elementType: findElementByKey(event.key) });
|
||||
} else if (event.metaKey && event.code === "KeyZ") {
|
||||
let lastEntry = stateHistory.pop();
|
||||
// If nothing was changed since last, take the previous one
|
||||
if (generateHistoryCurrentEntry() === lastEntry) {
|
||||
lastEntry = stateHistory.pop();
|
||||
}
|
||||
if (lastEntry !== undefined) {
|
||||
restoreHistoryEntry(lastEntry);
|
||||
}
|
||||
this.forceUpdate();
|
||||
event.preventDefault();
|
||||
}
|
||||
};
|
||||
|
||||
@ -1301,6 +1340,8 @@ class App extends React.Component<{}, AppState> {
|
||||
});
|
||||
lastX = x;
|
||||
lastY = y;
|
||||
// We don't want to save history when resizing an element
|
||||
skipHistory = true;
|
||||
this.forceUpdate();
|
||||
return;
|
||||
}
|
||||
@ -1319,6 +1360,8 @@ class App extends React.Component<{}, AppState> {
|
||||
});
|
||||
lastX = x;
|
||||
lastY = y;
|
||||
// We don't want to save history when dragging an element to initially size it
|
||||
skipHistory = true;
|
||||
this.forceUpdate();
|
||||
return;
|
||||
}
|
||||
@ -1347,6 +1390,8 @@ class App extends React.Component<{}, AppState> {
|
||||
if (this.state.elementType === "selection") {
|
||||
setSelection(draggingElement);
|
||||
}
|
||||
// We don't want to save history when moving an element
|
||||
skipHistory = true;
|
||||
this.forceUpdate();
|
||||
};
|
||||
|
||||
@ -1384,6 +1429,8 @@ class App extends React.Component<{}, AppState> {
|
||||
window.addEventListener("mousemove", onMouseMove);
|
||||
window.addEventListener("mouseup", onMouseUp);
|
||||
|
||||
// We don't want to save history on mouseDown, only on mouseUp when it's fully configured
|
||||
skipHistory = true;
|
||||
this.forceUpdate();
|
||||
}}
|
||||
/>
|
||||
@ -1407,6 +1454,10 @@ class App extends React.Component<{}, AppState> {
|
||||
viewBackgroundColor: this.state.viewBackgroundColor
|
||||
});
|
||||
save(this.state);
|
||||
if (!skipHistory) {
|
||||
pushHistoryEntry(generateHistoryCurrentEntry());
|
||||
}
|
||||
skipHistory = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user