Skip to content

feat(undo): reconcile native + CodeMirror undo via one app-level handler#10167

Open
jackkav wants to merge 1 commit into
developfrom
claude/undo-reconcile-handler
Open

feat(undo): reconcile native + CodeMirror undo via one app-level handler#10167
jackkav wants to merge 1 commit into
developfrom
claude/undo-reconcile-handler

Conversation

@jackkav

@jackkav jackkav commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

What

Follow-up to #10152 (opportunity # 4 in docs/undo-redo-baseline.md). Reconciles the two competing undo stacks through a single app-level handler.

Why

The Edit menu's Undo/Redo used role: 'undo'/'redo', which drive only Electron's native webContents.undo()/redo() stack. On macOS the menu accelerator swallows Cmd+Z before CodeMirror's own keymap can act on it — so in CodeMirror surfaces Cmd+Z did nothing useful (the native stack doesn't understand CodeMirror's document). Two stacks, native always wins, CodeMirror inert.

How

  • Menu Undo/Redo stop using role; they send('edit:undo')/send('edit:redo') to the focused window (labels + accelerators unchanged).
  • One renderer handler — editor-undo.ts, wired in renderer-listeners.ts — routes by focus:
    • focus inside a .CodeMirror wrapper → cm.undo()/redo() (CodeMirror's own history)
    • anything else → document.execCommand('undo'/'redo'), replicating exactly what the native role did for plain inputs.

No double-fire: the menu accelerator still prevents CodeMirror's keymap from firing independently (confirmed by the original baseline probe, where Cmd+Z on the URL bar was inert).

Test

  • New unit test editor-undo.test.ts (3 cases): CodeMirror focus drives cm history and does not touch the native stack; plain input falls back to execCommand; no-focus falls back to execCommand.
  • tsc + ESLint clean (no --fix).

closes INS-2877

The Edit menu's Undo/Redo used role: 'undo'/'redo', driving only the native
webContents stack. On macOS the menu accelerator swallows Cmd+Z before
CodeMirror's keymap, so CodeMirror surfaces had no working undo — two competing
stacks with the native one always winning and doing nothing useful for CM.

Menu Undo/Redo now send edit:undo/edit:redo to the focused window; a single
renderer handler (editor-undo.ts, wired in renderer-listeners.ts) routes by
focus: CodeMirror surfaces drive cm.undo()/redo(); everything else replays the
native execCommand, preserving prior plain-input behaviour. No double-fire: the
accelerator still keeps CM's own keymap from firing independently.
@github-actions

Copy link
Copy Markdown

✅ Circular References Report

Generated at: 2026-06-26T08:18:44.401Z
Status: ✅ NO CHANGE

Summary

Metric Base (develop) PR Change
Total Circular References 9 9 0 (0.00%)
Click to view all circular references in PR (9)
insomnia-inso/src/db/models/types.ts -> insomnia-inso/src/db/types.ts
insomnia/src/main/prompt-bridge.ts -> insomnia/src/main/window-utils.ts -> insomnia/src/main/plugin-window.ts
insomnia/src/main/window-utils.ts -> insomnia/src/main/plugin-window.ts
insomnia/src/network/network.ts -> insomnia-scripting-environment/src/objects/index.ts -> insomnia-scripting-environment/src/objects/collection.ts -> insomnia-scripting-environment/src/objects/response.ts
insomnia/src/network/network.ts -> insomnia/src/common/render.ts
insomnia/src/ui/components/settings/import-export.tsx -> insomnia/src/ui/components/modals/export-requests-modal.tsx
insomnia/src/ui/components/tabs/tab-list.tsx -> insomnia/src/ui/components/tabs/tab.tsx
insomnia/src/ui/components/templating/tag-editor-arg-sub-form.tsx -> insomnia/src/ui/components/templating/external-vault/external-vault-form.tsx
insomnia/src/ui/components/viewers/response-viewer.tsx -> insomnia/src/ui/components/viewers/response-multipart-viewer.tsx
Click to view all circular references in base branch (9)
insomnia-inso/src/db/models/types.ts -> insomnia-inso/src/db/types.ts
insomnia/src/main/prompt-bridge.ts -> insomnia/src/main/window-utils.ts -> insomnia/src/main/plugin-window.ts
insomnia/src/main/window-utils.ts -> insomnia/src/main/plugin-window.ts
insomnia/src/network/network.ts -> insomnia-scripting-environment/src/objects/index.ts -> insomnia-scripting-environment/src/objects/collection.ts -> insomnia-scripting-environment/src/objects/response.ts
insomnia/src/network/network.ts -> insomnia/src/common/render.ts
insomnia/src/ui/components/settings/import-export.tsx -> insomnia/src/ui/components/modals/export-requests-modal.tsx
insomnia/src/ui/components/tabs/tab-list.tsx -> insomnia/src/ui/components/tabs/tab.tsx
insomnia/src/ui/components/templating/tag-editor-arg-sub-form.tsx -> insomnia/src/ui/components/templating/external-vault/external-vault-form.tsx
insomnia/src/ui/components/viewers/response-viewer.tsx -> insomnia/src/ui/components/viewers/response-multipart-viewer.tsx

Analysis

No Change: This PR does not introduce or remove any circular references.


This report was generated automatically by comparing against the develop branch.

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