feat: Add HistoryManager for undo/redo functionality
This commit is contained in:
@@ -0,0 +1,62 @@
|
|||||||
|
import * as Y from 'yjs';
|
||||||
|
|
||||||
|
class HistoryManager {
|
||||||
|
private undoStack: Uint8Array[] = [];
|
||||||
|
private redoStack: Uint8Array[] = [];
|
||||||
|
private maxSize: number;
|
||||||
|
private doc: Y.Doc;
|
||||||
|
|
||||||
|
constructor(doc: Y.Doc, maxSize: number = 100) {
|
||||||
|
this.doc = doc;
|
||||||
|
this.maxSize = maxSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
push(update: Uint8Array) {
|
||||||
|
this.undoStack.push(update);
|
||||||
|
if (this.undoStack.length > this.maxSize) {
|
||||||
|
this.undoStack.shift();
|
||||||
|
}
|
||||||
|
// Clear redo stack when new action is performed
|
||||||
|
this.redoStack = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
undo() {
|
||||||
|
if (this.undoStack.length === 0) return false;
|
||||||
|
|
||||||
|
const update = this.undoStack.pop();
|
||||||
|
if (update) {
|
||||||
|
// Apply inverse of the update
|
||||||
|
Y.applyUpdate(this.doc, Y.encodeStateAsUpdate(this.doc, Y.createRelativePositionFromJSON(Y.createRelativePositionFromType(update as any))));
|
||||||
|
this.redoStack.push(update);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
redo() {
|
||||||
|
if (this.redoStack.length === 0) return false;
|
||||||
|
|
||||||
|
const update = this.redoStack.pop();
|
||||||
|
if (update) {
|
||||||
|
Y.applyUpdate(this.doc, update);
|
||||||
|
this.undoStack.push(update);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
canUndo(): boolean {
|
||||||
|
return this.undoStack.length > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
canRedo(): boolean {
|
||||||
|
return this.redoStack.length > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
clear() {
|
||||||
|
this.undoStack = [];
|
||||||
|
this.redoStack = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default HistoryManager;
|
||||||
Reference in New Issue
Block a user