https://stately.ai
Forgiving to mistakes
Allow exploration
Storage limits
Memory limits
Serialization concerns
UndoRedoSystem {
private undoStack: State[];
private redoStack: State[];
public state: State;
}
Stores change descriptor (less storage)
Applies update to build prev/next state (less memory)
interface State {
count: number;
}
interface Transaction {
patches: Patch[];
inversePatches: Patch[];
}
/**
Why not a function as the descriptor? Serialization and persistence!
* Patch {
* op: 'replace' | 'remove' | 'add'
* path: string[];
* value: any
* }
*/
UndoRedoSystem {
private undoStack: Transaction[];
private redoStack: Transaction[];
public state: State;
}
Updates can happen in multiple places
Updates can happen in different depths
To the user, this is one operation so when they undo, the shouldn't get partial inverse patches
function reparentShape() {
// multiple separate updates at once
updateShape();
updateSiblingShapes();
updateParent();
}
// Update in multiple depths:
function updateParent() {
// do some stuff
updateSiblingShapes();
}
function reparentShape() {
updateShape();
updateParent();
}
Sequential external updates with no time limits in between (append to the last update)
To the user, this is one operation so when they undo, the shouldn't get partial inverse patches
function renameShape(newName: string) {}
renameShape('new1')
renameShape('new2')
renameShape('newLastTimeIPromise')