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.historyandprojectState.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:
editsstores remove/mute/silence ranges. - Local undo/redo:
undoEditsandredoEditsmanage its ownhistory/future. - Preview lane ranges are kept in
editsand 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_ACTIONSin 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.