Skip to content

Undo/redo system via inverse operation stack #7

@FuJacob

Description

@FuJacob

Context

There is currently no undo/redo system. Sim implements undo/redo as a thin wrapper over the socket system — undo is just another edit that generates an inverse operation and sends it through the normal operation queue.

What to build

Per-user undo/redo stacks

  • Each user maintains a local undo stack and redo stack
  • Every operation records its inverse:
    • Add node → inverse: Remove node (snapshot full node state)
    • Remove node → inverse: Add node (restore from snapshot)
    • Move node → inverse: Move node (original position)
    • Update text → inverse: Update text (previous value)
    • Add edge → inverse: Remove edge
    • Remove edge → inverse: Add edge (snapshot edge)

Undo execution

  • Cmd+Z / Ctrl+Z: Pop from undo stack → push to redo stack → execute inverse op through the operation queue
  • Cmd+Shift+Z / Ctrl+Y: Pop from redo stack → push to undo stack → execute forward op through the operation queue
  • Inverse operations flow through the normal WebSocket system — other users see the change in real-time

Coalescing consecutive ops

  • Consecutive same-type operations should coalesce in the stack
  • e.g., dragging a node through 50 positions → single undo entry (start position → end position)
  • Typing in a text field → coalesce by time window or word boundary

Multiplayer-safe stack pruning

  • When a remote user deletes an entity, prune any undo entries that reference it
  • Example: User A has "add edge to Block X" in undo stack, User B deletes Block X → prune that entry
  • Prevents executing inverse ops on entities that no longer exist

Circular recording prevention

  • Mark undo/redo operations as isUndo: true during execution
  • These operations should NOT be recorded into the undo stack themselves

Current code references

  • frontend/src/canvas/model/useCanvasDocument.ts — command functions that would generate undo entries
  • frontend/src/canvas/hooks/useCanvasShortcutContainer.ts — keyboard shortcut handling (add Cmd+Z here)

Acceptance criteria

  • Cmd+Z undoes last local action
  • Cmd+Shift+Z redoes last undone action
  • Undo/redo operations broadcast to other users via WebSocket
  • Consecutive drag/type operations coalesce into single undo entries
  • Stack entries pruned when referenced entities are deleted by remote users
  • Undo operations don't create new undo entries

Metadata

Metadata

Assignees

No one assigned

    Labels

    FEFrontend work

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions