Editor undo/redo is non-functional (history never advances, no state snapshots taken) #70

Closed
opened 2026-09-14 03:17:02 +00:00 by Mark · 0 comments
Owner

Where: src/pages/Editor.tsx:28-29 (history is frozen at length 1) and :229-239 (handleUndo / handleRedo).

Bug:

  • const [history] = useState<StitchPath[][]>([DEMO_PATHS]) — length is permanently 1.
  • handleUndo early-returns unless historyIndex > 0 (always 0).
  • handleRedo early-returns unless historyIndex < history.length - 1 (always 0 < 0).
  • None of the mutating handlers (handleNodeDrag, handleAddNodeAt, handleDeleteSelectedNodes, handleUpdateNodeType, handleAddNodeToSelection, handleFinishPath) push to history.

Fix consistent with existing patterns:
Copy pushHistory from useWorkspace.ts:118-127. Concretely:

  1. Convert history from useState<StitchPath[][]>([DEMO_PATHS]) to [history, setHistory] = useState<StitchPath[][]>([]) and seed it on first path-mutating action.
  2. Before every mutating handler runs, do setHistory(h => { const next = h.slice(0, historyIndex + 1); next.push(deepClone(paths)); return next.length > 50 ? next.slice(next.length - 50) : next; }); setHistoryIndex(i => i + 1).
  3. handleUndo: setPaths(deepClone(history[historyIndex - 1])); setHistoryIndex(i => i - 1).
  4. handleRedo: symmetric.

Reference impl lives at useWorkspace.ts:118-127, 244-264. Apply the same shape here.

**Where:** `src/pages/Editor.tsx:28-29` (`history` is frozen at length 1) and `:229-239` (`handleUndo` / `handleRedo`). **Bug:** - `const [history] = useState<StitchPath[][]>([DEMO_PATHS])` — length is permanently 1. - `handleUndo` early-returns unless `historyIndex > 0` (always 0). - `handleRedo` early-returns unless `historyIndex < history.length - 1` (always 0 < 0). - None of the mutating handlers (`handleNodeDrag`, `handleAddNodeAt`, `handleDeleteSelectedNodes`, `handleUpdateNodeType`, `handleAddNodeToSelection`, `handleFinishPath`) push to history. **Fix consistent with existing patterns:** Copy `pushHistory` from `useWorkspace.ts:118-127`. Concretely: 1. Convert `history` from `useState<StitchPath[][]>([DEMO_PATHS])` to `[history, setHistory] = useState<StitchPath[][]>([])` and seed it on first path-mutating action. 2. Before every mutating handler runs, do `setHistory(h => { const next = h.slice(0, historyIndex + 1); next.push(deepClone(paths)); return next.length > 50 ? next.slice(next.length - 50) : next; }); setHistoryIndex(i => i + 1)`. 3. `handleUndo`: `setPaths(deepClone(history[historyIndex - 1])); setHistoryIndex(i => i - 1)`. 4. `handleRedo`: symmetric. Reference impl lives at `useWorkspace.ts:118-127, 244-264`. Apply the same shape here.
Mark 2026-09-14 03:17:02 +00:00
Sign in to join this conversation.
No description provided.