fix(desktop): paste text undoable via Ctrl+Z on Windows (#6531) / 修复ctrl+z无法撤回ctrl+v的内容 - #6571
Merged
Merged
Conversation
JesonChou
force-pushed
the
fix/issue-6531-paste-undo
branch
from
July 16, 2026 09:22
23c4478 to
a85fbf9
Compare
On Windows Ctrl+Z has no job-control semantics, so repurpose it as undo for paste operations. A LIFO undo stack (capped at 50 entries) records the input state before each paste; Ctrl+Z pops and restores. Folded pastes and image refs participate without double-pushing.
…6531) Replace the unreliable browser-native undo approach (execCommand / setRangeText in WebView2) with an explicit paste undo stack in the Composer. Before each paste the current input text is pushed onto a ref-managed stack; a Ctrl+Z keydown handler pops and restores the last saved state. Falls through to browser-native undo when the stack is empty, preserving normal text-editing undo.
JesonChou
force-pushed
the
fix/issue-6531-paste-undo
branch
from
July 17, 2026 17:16
a85fbf9 to
7e10583
Compare
Contributor
Author
|
@SivanCola 大佬,可以审下这个PR么?这个bug也是比较久了,关于desktop剪切板体验的。当前desktop对于ctrl+v到输入框的内容不能通过ctrl+z撤回掉,对于大段文字的粘贴修改体验比较差。 |
Problem: Desktop paste is applied through React after preventing the browser default, so Ctrl+Z cannot see it. The initial fix used a global text-only stack that crossed drafts and missed folded pastes. Root cause: Programmatic edits live outside the WebView native undo history, while a component-global snapshot cannot model per-draft structured composer state. Fix: - Track bounded paste and cut transactions per draft with text, invocation, folded-block, counter, and selection state. - Intercept undo and redo only at exact transaction boundaries so native typing undo remains intact. - Clear histories on replace and submit, and keep TUI suspend behavior unchanged. - Add regressions for short paste, redo, folded paste, and cross-draft isolation. Verification: - pnpm test:typecheck - pnpm test - pnpm build - go test ./... (desktop) - go test ./internal/cli/...
Problem: Programmatic paste redo survived later native edits, and rich-composer undo snapshots lost the invocation-side caret anchor. Root cause: The custom redo stack was cleared only by another recorded transaction, while edit snapshots and selection restoration stored text offsets without afterInvocationId. The Windows Ctrl+Y fallback was also unreachable because the existing YOLO shortcut owns that chord. Fix: Invalidate per-draft redo on native or structured composer edits, preserve complete rich selections across paste and restore paths, keep invocation offsets stable for menu paste, and reserve Ctrl+Y for the established approval shortcut. Merge the latest main-v2 baseline. Verification: pnpm test; pnpm test:typecheck; pnpm build; desktop go test ./...; go test ./internal/cli/...; git diff --check. Co-authored-by: SivanCola <32437197+SivanCola@users.noreply.github.com>
Problem: Programmatic paste transactions could jump ahead of newer browser edits, become unavailable while a folded preview was open, and miss Ctrl+Y redo after the YOLO shortcut was rebound. Root cause: The custom history inferred ordering only from snapshot equality and treated preview-only UI state as document state. Rich-composer programmatic edits also did not identify their history origin. Fix: Track native undo/redo barriers per draft, preserve mixed custom/native ordering, separate browser and programmatic rich-input changes, keep preview state out of history matching, and support the platform Ctrl+Y fallback without overriding the configured YOLO shortcut. Verification: pnpm test:all pnpm build go test ./... cd desktop && go test ./...
Integration: Sync PR esengine#6571 with main-v2 at 87999b9 before the user-facing shortcut follow-up. Verification: The relevant Composer, shortcut, locale, and guide paths have no upstream conflicts; full verification follows in the next commit.
Problem: Composer undo and redo behavior was not discoverable in Settings, help, context menus, or the user guides. YOLO tooltips also kept showing its default binding after a rebind. Root cause: The composer handled editing chords and Reasonix transactions locally instead of registering the actions in the shared shortcut catalog. The custom context menu exposed clipboard actions only, and documentation still described Ctrl/Cmd+Y as YOLO-only. Fix: Register locked platform undo and redo actions, protect their editing chords from legacy global bindings, reuse the transaction history from the context menu, render live YOLO shortcut labels, and update English and Chinese guidance. Verification: pnpm test:all pnpm build go test ./... in desktop Real browser checks for Settings rows, live YOLO rebind labels, context-menu undo/redo, and a clean console
Problem: The rich composer did not open Reasonix's edit context menu, so drafts containing skill or subagent tokens could not use the transaction-aware Undo and Redo actions. Root cause: Only the plain textarea wired the shared context-menu handler; RichComposerInput did not expose or forward a contextmenu event. Fix: Forward context-menu events from RichComposerInput and reuse the existing Composer edit menu for both editable surfaces. Add regression coverage for undoing and redoing a paste after an inline invocation. Verification: - pnpm exec tsx src/__tests__/composer-goal-toggle.test.tsx - pnpm exec tsx src/__tests__/composer-session-draft.test.tsx - pnpm exec tsx src/__tests__/composer-context-menu-clipboard.test.tsx - pnpm test:typecheck - pnpm build - git diff --check Co-authored-by: SivanCola <32437197+SivanCola@users.noreply.github.com>
Problem: Legacy custom YOLO bindings on Ctrl/Cmd+Z or Ctrl/Cmd+Shift+Z intercepted Composer undo and redo, toggling approval mode instead of editing the draft. Root cause: Composer matched the local YOLO shortcut before its transaction-aware history handler and did not apply the reserved editing-chord policy used globally. Fix: Exclude reserved Composer undo and redo chords from local YOLO handling. Add upgrade regression coverage for legacy bindings, rebound YOLO, and the default Ctrl+Y behavior. Verification: - pnpm exec tsx src/__tests__/composer-session-draft.test.tsx (130 passed) - pnpm exec tsx src/__tests__/keyboard-shortcuts.test.ts (71 passed) - pnpm exec tsx src/__tests__/composer-goal-toggle.test.tsx (185 passed) - pnpm exec tsx src/__tests__/shortcut-recorder.test.tsx (25 passed) - pnpm test:typecheck - pnpm exec vite build --logLevel error - git diff --check Co-authored-by: SivanCola <32437197+SivanCola@users.noreply.github.com>
Collaborator
做了一些修复,下个版本就带上去 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #6531.
Desktop text paste is applied programmatically after the browser default is prevented, so WebView2 cannot reliably place that edit in its native undo history. This PR adds a bounded, per-draft transaction history for programmatic composer edits while preserving the browser-native history for ordinary typing.
afterInvocationId, so undo returns the caret to the correct side of an inline skill or subagent token.main-v2through87999b974.This PR changes the Desktop frontend and user-facing documentation; it does not change CLI/TUI behavior or the embedded terminal.
Verification
pnpm test:allpnpm buildgo test ./...cd desktop && go test ./...git diff --checkAll checks passed locally on commit
3afcafb03.Compatibility
Cache and security impact