diff --git a/frontend/src/history/HistoryManager.ts b/frontend/src/history/HistoryManager.ts new file mode 100644 index 0000000..942b02f --- /dev/null +++ b/frontend/src/history/HistoryManager.ts @@ -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; \ No newline at end of file