Undo and Redo
Klippy provides fast, reliable history across the editor. Project‑level changes (media/text/zoom/props, captions, transitions, settings) go into a unified history stack; transcript‑driven range edits have an additional local stack. Most multi‑step operations are batched into a single, semantic entry (e.g., “Added 6 files”).
1) Keyboard & UI
- Undo: Ctrl/Cmd+Z
- Redo: Ctrl/Cmd+Shift+Z (or Ctrl/Cmd+Y)
2) Project‑level history
- Stack fields:
projectState.history
andprojectState.future
. - Actions:
recordHistory
,undo
,redo
,clearHistory
. - When content changes (e.g.,
setMediaFiles
,setTextElements
), durations are recomputed and a history entry is recorded. - Transitions, captions, canvas size, export settings, recording state are included in snapshots.
3) Edits‑level history
- Slice:
edits
stores remove/mute/silence ranges. - Local undo/redo:
undoEdits
andredoEdits
manage its ownhistory
/future
. - Preview lane ranges are kept in
edits
and mirrored to the timeline preview controls.
4) Unified history middleware
The store wires middlewares in a specific order (app/store/index.ts
):
- StateUpdateQueue — groups related updates before observers run.
- DurationMiddleware — debounced recompute after content changes.
- Validation — ensures invariants for time ranges/rows.
- UnifiedHistory — attaches a single meaningful history entry per logical action.
- CombinedUndoRedo — mirrors edits slice undo/redo when project undo/redo is invoked, keeping both stacks consistent.
5) Semantic batching
For flows that touch many items (import, bulk caption updates, transcript suggestions), we use runInBatch(dispatch, fn, description)
so the user sees a single concise entry in history.
- Examples: stock media adds, global drops, transcript suggestion preview/apply, caption generate/import.
- Inside a batch, child actions set
meta.skipHistory: true
; the batch writes one final entry with a clear description. - Guidelines documented in
docs/HISTORY_AND_BATCHING.md
.
6) What’s not tracked
- Ephemeral/UI‑only actions (playhead moves, selection, zoom changes) are excluded from history.
- These are filtered by
NON_HISTORY_ACTIONS
in the history middleware.
7) Tips
- Use batching for multi‑dispatch flows to avoid spamming the history panel.
- Provide descriptive labels (e.g., “Inserted 3 media items”, “Applied transcript edits”).
- Prefer selectors for derived values when building undoable UI, to keep snapshots small.