fix(chat): prevent shell prefix from corrupting input
This commit is contained in:
@@ -1402,6 +1402,19 @@ const ChatInputComponent: React.FC<ChatInputProps> = ({ onOpenSettings, scrollTo
|
|||||||
// Uses keyCode === 229 fallback for WebKit where compositionend fires before keydown.
|
// Uses keyCode === 229 fallback for WebKit where compositionend fires before keydown.
|
||||||
if (isIMECompositionEvent(e)) return;
|
if (isIMECompositionEvent(e)) return;
|
||||||
|
|
||||||
|
// Enter shell mode before CodeMirror inserts the trigger. Keeping the
|
||||||
|
// document unchanged also keeps the caret at the start for the first
|
||||||
|
// command character.
|
||||||
|
if (inputMode === 'normal' && e.key === '!') {
|
||||||
|
const selection = composerRef.current?.getSelection();
|
||||||
|
if (selection?.start === 0 && selection.end === 0) {
|
||||||
|
e.preventDefault();
|
||||||
|
setInputMode('shell');
|
||||||
|
closeAutocomplete();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (inputMode === 'shell' && e.key === 'Escape') {
|
if (inputMode === 'shell' && e.key === 'Escape') {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
setInputMode('normal');
|
setInputMode('normal');
|
||||||
@@ -1723,13 +1736,20 @@ const ChatInputComponent: React.FC<ChatInputProps> = ({ onOpenSettings, scrollTo
|
|||||||
const inputSource: FileMentionAutocompleteInputSource = isPasteInput ? 'paste' : 'manual';
|
const inputSource: FileMentionAutocompleteInputSource = isPasteInput ? 'paste' : 'manual';
|
||||||
|
|
||||||
// A leading `!` switches the composer into shell mode and is consumed.
|
// A leading `!` switches the composer into shell mode and is consumed.
|
||||||
|
// Mobile keyboards and paste may update the document without a usable
|
||||||
|
// keydown, so consume the trigger in the same editor transaction rather
|
||||||
|
// than moving the caret in a later frame against stale text.
|
||||||
if (inputMode === 'normal' && value.startsWith('!')) {
|
if (inputMode === 'normal' && value.startsWith('!')) {
|
||||||
const shellCommand = value.slice(1);
|
const shellCommand = value.slice(1);
|
||||||
const nextCursor = Math.max(0, selection.start - 1);
|
const nextCursor = Math.max(0, selection.start - 1);
|
||||||
setInputMode('shell');
|
setInputMode('shell');
|
||||||
setMessage(shellCommand);
|
|
||||||
closeAutocomplete();
|
closeAutocomplete();
|
||||||
requestAnimationFrame(() => composerRef.current?.setSelection(nextCursor));
|
const editor = composerRef.current;
|
||||||
|
if (editor) {
|
||||||
|
editor.replaceRange(0, 1, '', nextCursor);
|
||||||
|
} else {
|
||||||
|
setMessage(shellCommand);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user