mirror of
https://github.com/Kilo-Org/kilocode.git
synced 2026-09-19 01:51:21 +08:00
fix(vscode): restore undo and redo in the chat input
VS Code's webview preload intercepts Ctrl/Cmd+Z and Ctrl+Y and forwards them to the workbench, so the prompt input stopped propagation but never performed the edit. A webview keypress has no native undo default action on macOS, so the undo stack stayed untouched and the shortcuts did nothing. Perform the edit with document.execCommand on the same native undo stack real typing builds, and match keyCode like VS Code does so non-Latin keyboard layouts no longer leak the key back to the workbench. The Agent Manager New Worktree prompt had the same gap with no guard at all; it now shares the same helper through prompt-input-utils.
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"kilo-code": patch
|
||||
---
|
||||
|
||||
Fix Ctrl/Cmd+Z, Ctrl/Cmd+Shift+Z, and Ctrl+Y undo and redo in the chat input, including on non-Latin keyboard layouts
|
||||
@@ -44,7 +44,7 @@ import { useSpeechToText } from "../src/components/speech-to-text/useSpeechToTex
|
||||
import { useSpeechToTextModels } from "../src/context/speech-to-text-models"
|
||||
import { createSpeechShortcut } from "../src/components/speech-to-text/shortcut"
|
||||
import { convertToMentionPath, insertPathMentions } from "../src/utils/path-mentions"
|
||||
import { insertSpacedText } from "../src/components/chat/prompt-input-utils"
|
||||
import { insertSpacedText, undoKey } from "../src/components/chat/prompt-input-utils"
|
||||
import { useSlashCommand } from "../src/hooks/useSlashCommand"
|
||||
import { BranchSelect, BranchSelectPopover } from "../src/components/shared/BranchSelect"
|
||||
import { tracker } from "./telemetry"
|
||||
@@ -451,8 +451,14 @@ export const NewWorktreeDialog: Component<{
|
||||
}
|
||||
|
||||
const undo = (e: KeyboardEvent) => {
|
||||
if (e.key !== "z" || (!e.metaKey && !e.ctrlKey) || e.shiftKey || prior === null) return
|
||||
const action = undoKey(e)
|
||||
if (!action) return
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
if (action === "redo" || prior === null) {
|
||||
document.execCommand(action)
|
||||
return
|
||||
}
|
||||
const restored = prior
|
||||
cancel()
|
||||
setPrompt(restored)
|
||||
|
||||
@@ -60,6 +60,7 @@ import {
|
||||
memoryRest,
|
||||
type SandboxDefaultState,
|
||||
type SandboxState,
|
||||
undoKey,
|
||||
} from "./prompt-input-utils"
|
||||
import { sandboxMessages } from "./prompt-sandbox-messages"
|
||||
import type { ExtensionMessage, ReviewCommentEntry, SendMessageFailedMessage, TextPart } from "../../types/messages"
|
||||
@@ -1266,6 +1267,19 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
|
||||
return true
|
||||
}
|
||||
|
||||
// Native undo/redo. Plain undo falls through to handleKeyDown when an
|
||||
// Enhance result can be reverted first.
|
||||
const undo = (e: KeyboardEvent): boolean => {
|
||||
const action = undoKey(e)
|
||||
if (!action) return false
|
||||
e.stopPropagation()
|
||||
if (action === "undo" && preEnhanceText !== null) return false
|
||||
e.preventDefault()
|
||||
if (readonly()) return true
|
||||
document.execCommand(action)
|
||||
return true
|
||||
}
|
||||
|
||||
const handleKeyDown = (e: KeyboardEvent) => {
|
||||
if (goal.pending()) {
|
||||
escape(e)
|
||||
@@ -1273,7 +1287,7 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
|
||||
}
|
||||
if (locked()) return
|
||||
// Undo enhanced prompt with Ctrl+Z / ⌘Z
|
||||
if (e.key === "z" && (e.metaKey || e.ctrlKey) && !e.shiftKey && preEnhanceText !== null) {
|
||||
if (undoKey(e) === "undo" && preEnhanceText !== null) {
|
||||
e.preventDefault()
|
||||
const restored = preEnhanceText
|
||||
preEnhanceText = null
|
||||
@@ -2003,10 +2017,7 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
|
||||
onInput={handleInput}
|
||||
onKeyDown={(e) => {
|
||||
if (speechDown(e)) return
|
||||
const key = e.key.toLowerCase()
|
||||
if ((e.ctrlKey || e.metaKey) && !e.altKey && (key === "z" || (key === "y" && !e.shiftKey))) {
|
||||
e.stopPropagation()
|
||||
}
|
||||
if (undo(e)) return
|
||||
handleKeyDown(e)
|
||||
}}
|
||||
onKeyUp={(e) => {
|
||||
|
||||
@@ -34,6 +34,19 @@ export function applySandboxStates(current: Record<string, SandboxState>, next:
|
||||
return { ...current, [next.sessionID]: state }
|
||||
}
|
||||
|
||||
// VS Code's webview preload intercepts Ctrl/Cmd+Z and Ctrl+Y and forwards them
|
||||
// to the workbench, which can undo an unrelated editor (#13724). Callers must
|
||||
// stop propagation, and because a webview keypress has no native undo default
|
||||
// action on macOS, perform the edit with document.execCommand (#14191).
|
||||
// Match keyCode like VS Code does so non-Latin layouts stay in lockstep.
|
||||
export function undoKey(e: KeyboardEvent): "undo" | "redo" | undefined {
|
||||
if (!(e.ctrlKey || e.metaKey) || e.altKey) return
|
||||
const z = e.keyCode === 90 || e.key.toLowerCase() === "z"
|
||||
const y = e.keyCode === 89 || e.key.toLowerCase() === "y"
|
||||
if (z) return e.shiftKey ? "redo" : "undo"
|
||||
if (y && !e.shiftKey) return "redo"
|
||||
}
|
||||
|
||||
export function fileName(path: string): string {
|
||||
const normalized = path.replaceAll("\\", "/").replace(/\/+$/, "")
|
||||
return normalized.split("/").pop() ?? normalized
|
||||
|
||||
Reference in New Issue
Block a user