Skip to content

Refactor: extract annotation undo/redo into CanvasHistory#6

Merged
GamalAnwar merged 1 commit into
masterfrom
claude/solid-refactor-canvas-history
Jun 17, 2026
Merged

Refactor: extract annotation undo/redo into CanvasHistory#6
GamalAnwar merged 1 commit into
masterfrom
claude/solid-refactor-canvas-history

Conversation

@GamalAnwar

Copy link
Copy Markdown
Contributor

Summary

First substantive EditorView decomposition slice (behavior-preserving).

EditorView held the annotation undo/redo as two loose @State arrays (undoStack/redoStack) plus inline push/cap-at-100/clear-redo and pop-and-apply logic. This moves the stack ownership and the rules into a dedicated, testable CanvasHistory value type:

canvasHistory.record(current)              // push + cap + clear redo
canvasHistory.undo(current:) -> CanvasState?  // swap + return state to apply
canvasHistory.redo(current:) -> CanvasState?
canvasHistory.canUndo / canRedo            // toolbar enablement

The view now records snapshots and applies whatever state CanvasHistory returns.

Scope / safety

  • Behavior-preserving. The image-level undo stacks (imageUndoStack/imageRedoStack) are intentionally left untouched — this slice is just the annotation history.
  • undo()/redo() keep the exact same ordering (image pop first, then canvas state), and the empty-guard semantics are preserved via the optional return.

Tests

CanvasHistoryTests (7 cases): empty state, record enables undo, undo returns previous + enables redo, redo swap, record clears redo, nil on empty, and cap-drops-oldest.

🤖 Generated with Claude Code


Generated by Claude Code

EditorView held the annotation undo/redo as two loose @State arrays plus inline
push/cap/clear-redo and pop/apply logic. Move the stack ownership and rules into
a testable CanvasHistory value type; the view records snapshots and applies the
state CanvasHistory returns. Behavior-preserving (image-level undo stacks are
unchanged). Adds CanvasHistoryTests (7 cases).
@GamalAnwar GamalAnwar merged commit ec6c4dc into master Jun 17, 2026
1 check passed
GamalAnwar added a commit that referenced this pull request Jun 17, 2026
…ndo (#7)

Generalize CanvasHistory into BoundedHistory<Snapshot> and back the image-undo
stack with it (BoundedHistory<NSImage>, limit 20) instead of inline @State arrays.
CanvasHistory becomes a typealias, so #6's usage/tests are unchanged. Behavior-
preserving: image and canvas histories pop independently. Adds BoundedHistoryTests
(4 cases). CI green.
@GamalAnwar GamalAnwar deleted the claude/solid-refactor-canvas-history branch June 18, 2026 07:35
GamalAnwar pushed a commit that referenced this pull request Jun 18, 2026
…ndo too

The image-level undo/redo was still two loose @State [NSImage] arrays with inline
push/cap-at-20/pop logic in EditorView, duplicating the rules just extracted for
the annotation canvas. Generalize CanvasHistory into BoundedHistory<Snapshot>
(CanvasHistory becomes a typealias, so #6's usage and tests are unchanged) and
back the image stack with BoundedHistory<NSImage>(limit: 20).

Behavior-preserving: image and canvas histories are still popped independently in
undo()/redo() (image best-effort, canvas guarded). Adds BoundedHistoryTests (4
cases) pinning the generic behavior with a non-CanvasState type.
GamalAnwar added a commit that referenced this pull request Jun 18, 2026
Move EditorView's annotation undo/redo (two loose @State arrays + inline
push/cap/pop/apply) into a testable CanvasHistory value type. Behavior-preserving;
image-level undo stacks unchanged. Adds CanvasHistoryTests (7 cases). CI green.
GamalAnwar added a commit that referenced this pull request Jun 18, 2026
…ndo (#7)

Generalize CanvasHistory into BoundedHistory<Snapshot> and back the image-undo
stack with it (BoundedHistory<NSImage>, limit 20) instead of inline @State arrays.
CanvasHistory becomes a typealias, so #6's usage/tests are unchanged. Behavior-
preserving: image and canvas histories pop independently. Adds BoundedHistoryTests
(4 cases). CI green.
GamalAnwar pushed a commit that referenced this pull request Jun 18, 2026
…ndo too

The image-level undo/redo was still two loose @State [NSImage] arrays with inline
push/cap-at-20/pop logic in EditorView, duplicating the rules just extracted for
the annotation canvas. Generalize CanvasHistory into BoundedHistory<Snapshot>
(CanvasHistory becomes a typealias, so #6's usage and tests are unchanged) and
back the image stack with BoundedHistory<NSImage>(limit: 20).

Behavior-preserving: image and canvas histories are still popped independently in
undo()/redo() (image best-effort, canvas guarded). Adds BoundedHistoryTests (4
cases) pinning the generic behavior with a non-CanvasState type.
GamalAnwar added a commit that referenced this pull request Jun 18, 2026
…ndo too

The image-level undo/redo was still two loose @State [NSImage] arrays with inline
push/cap-at-20/pop logic in EditorView, duplicating the rules just extracted for
the annotation canvas. Generalize CanvasHistory into BoundedHistory<Snapshot>
(CanvasHistory becomes a typealias, so #6's usage and tests are unchanged) and
back the image stack with BoundedHistory<NSImage>(limit: 20).

Behavior-preserving: image and canvas histories are still popped independently in
undo()/redo() (image best-effort, canvas guarded). Adds BoundedHistoryTests (4
cases) pinning the generic behavior with a non-CanvasState type.
GamalAnwar added a commit that referenced this pull request Jun 18, 2026
Move EditorView's annotation undo/redo (two loose @State arrays + inline
push/cap/pop/apply) into a testable CanvasHistory value type. Behavior-preserving;
image-level undo stacks unchanged. Adds CanvasHistoryTests (7 cases). CI green.
GamalAnwar added a commit that referenced this pull request Jun 18, 2026
…ndo (#7)

Generalize CanvasHistory into BoundedHistory<Snapshot> and back the image-undo
stack with it (BoundedHistory<NSImage>, limit 20) instead of inline @State arrays.
CanvasHistory becomes a typealias, so #6's usage/tests are unchanged. Behavior-
preserving: image and canvas histories pop independently. Adds BoundedHistoryTests
(4 cases). CI green.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants