Implement document-wide undo/redo
Snapshot-based, like the existing JSON export/import round-trip (snapshot()/replaceDocument()) rather than a patch/command log -- simple and provably correct for a document this size. - document.ts: a deep watch on `doc` tracks a "content fingerprint" (sheets + locale + csvDelimiter, deliberately excluding selection/activeObjectId, so moving the cursor is never an undo step) and debounces commits by 150ms -- long enough to coalesce a resize-drag's per-mousemove calls into one step, short enough that two genuinely separate quick actions don't merge. A new edit after an undo immediately drops the redo branch (not debounced, so a bound button is never briefly wrong). undo()/redo() flush any pending change first, then pop/apply a snapshot via a new applyDocumentState() core that replaceDocument() also uses -- replaceDocument() (JSON import "replace", "reset to seed") additionally resets history, since loading a different document shouldn't leave the old one undoable into it; undo/redo themselves must not (that's the very stack they're unwinding). - TableGrid.vue: Strg/Cmd+Z undoes, Strg/Cmd+Y or +Shift+Z redoes, deferring to a cell editor's native undo while one is open (the existing `if (editing.value) return` guard already covers this). - App.vue: a window-level fallback for when no table has focus, skipped whenever focus sits in any text field so their own native undo keeps working. - AppToolbar.vue: ↶/↷ buttons, disabled via store.canUndo/canRedo. Verified interactively against the dev server with Playwright: the toolbar button enables the instant a change happens (not after the debounce); separately-timed edits each undo as their own step; a multi-tick resize drag undoes in one step back to the original width; Ctrl+Z, Ctrl+Y and the toolbar buttons all work. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -736,6 +736,16 @@ function onKeydown(e: KeyboardEvent) {
|
||||
e.stopPropagation();
|
||||
return store.pasteClipboard();
|
||||
}
|
||||
if (k === 'z' && !e.shiftKey) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
return store.undo();
|
||||
}
|
||||
if ((k === 'z' && e.shiftKey) || k === 'y') {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
return store.redo();
|
||||
}
|
||||
}
|
||||
|
||||
switch (e.key) {
|
||||
|
||||
Reference in New Issue
Block a user