mirror of
https://github.com/wassname/talk.git
synced 2026-06-30 16:50:44 +08:00
66 lines
1.2 KiB
JavaScript
66 lines
1.2 KiB
JavaScript
/**
|
|
* Simple size limited Undo stack.
|
|
*/
|
|
export default class Undo {
|
|
/**
|
|
* undoStack contains all known values.
|
|
* The last value of this stack represent
|
|
* the most recent change.
|
|
*/
|
|
undoStack = [];
|
|
redoStack = [];
|
|
size;
|
|
|
|
constructor(size = 100) {
|
|
this.size = size;
|
|
}
|
|
|
|
clear() {
|
|
this.undoStack = [];
|
|
this.redoStack = [];
|
|
}
|
|
|
|
canUndo() {
|
|
return this.undoStack.length > 1;
|
|
}
|
|
|
|
canRedo() {
|
|
return this.redoStack.length;
|
|
}
|
|
|
|
undo() {
|
|
if (!this.canUndo()) {
|
|
throw new Error('Nothing to undo');
|
|
}
|
|
const cur = this.undoStack.pop();
|
|
this.redoStack.push(cur);
|
|
return this.undoStack[this.undoStack.length - 1];
|
|
}
|
|
|
|
redo() {
|
|
if (!this.canRedo()) {
|
|
throw new Error('Nothing to redo');
|
|
}
|
|
const x = this.redoStack.pop();
|
|
this.undoStack.push(x);
|
|
return x;
|
|
}
|
|
|
|
save(x, ...meta) {
|
|
// Ignore if we already have that saved.
|
|
if (
|
|
this.undoStack.length &&
|
|
this.undoStack[this.undoStack.length - 1][0] === x
|
|
) {
|
|
return;
|
|
}
|
|
this.undoStack.push([x, ...meta]);
|
|
|
|
// Adhere to maximum size.
|
|
if (this.undoStack.length > this.size) {
|
|
this.undoStack.splice(0, 1);
|
|
}
|
|
this.redoStack = [];
|
|
}
|
|
}
|