From 5193539fb4f12dfe990519642991482a92bad0fe Mon Sep 17 00:00:00 2001 From: Ammar Date: Thu, 23 Oct 2025 20:04:12 -0500 Subject: [PATCH 1/2] =?UTF-8?q?=F0=9F=A4=96=20Allow=20interrupt=20(Ctrl+C)?= =?UTF-8?q?=20in=20ChatInput=20when=20no=20text=20is=20selected?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously, Ctrl+C interrupt only worked when focus was outside editable elements. This prevented interrupting while ChatInput was focused. Now checks for text selection: - No selection → interrupt stream (new behavior) - Has selection → browser copy (existing behavior) This allows users to quickly interrupt without first focusing elsewhere, while preserving the copy functionality when text is selected. --- src/hooks/useAIViewKeybinds.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/hooks/useAIViewKeybinds.ts b/src/hooks/useAIViewKeybinds.ts index 982137c85..263ab0578 100644 --- a/src/hooks/useAIViewKeybinds.ts +++ b/src/hooks/useAIViewKeybinds.ts @@ -67,15 +67,19 @@ export function useAIViewKeybinds({ } // Normal stream interrupt (non-compaction) - // Don't intercept if user is typing in an input field - if (!isEditableElement(e.target) && (canInterrupt || showRetryBarrier)) { + // Allow interrupt in editable elements if there's no text selection + // This way Ctrl+C works for both copy (when text is selected) and interrupt (when not) + const hasSelection = window.getSelection()?.toString().length ?? 0 > 0; + const inEditableElement = isEditableElement(e.target); + + if ((canInterrupt || showRetryBarrier) && (!inEditableElement || !hasSelection)) { e.preventDefault(); setAutoRetry(false); // User explicitly stopped - don't auto-retry void window.api.workspace.interruptStream(workspaceId); return; } - // Let browser handle Ctrl+C (copy) in editable elements + // Let browser handle Ctrl+C (copy) when there's a selection return; } From 56bc6caf831af6247ba1615e0c18c984c391f2b1 Mon Sep 17 00:00:00 2001 From: Ammar Date: Thu, 23 Oct 2025 20:07:33 -0500 Subject: [PATCH 2/2] =?UTF-8?q?=F0=9F=A4=96=20Fix=20selection=20detection?= =?UTF-8?q?=20for=20textarea=20elements?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use selectionStart/selectionEnd for input/textarea elements instead of window.getSelection(), which doesn't work for form controls. This ensures copy (Ctrl+C) works correctly when text is selected in ChatInput's textarea, while still allowing interrupt when no selection. --- src/hooks/useAIViewKeybinds.ts | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/hooks/useAIViewKeybinds.ts b/src/hooks/useAIViewKeybinds.ts index 263ab0578..1086af3a0 100644 --- a/src/hooks/useAIViewKeybinds.ts +++ b/src/hooks/useAIViewKeybinds.ts @@ -69,8 +69,21 @@ export function useAIViewKeybinds({ // Normal stream interrupt (non-compaction) // Allow interrupt in editable elements if there's no text selection // This way Ctrl+C works for both copy (when text is selected) and interrupt (when not) - const hasSelection = window.getSelection()?.toString().length ?? 0 > 0; const inEditableElement = isEditableElement(e.target); + let hasSelection = false; + + if (inEditableElement) { + // For input/textarea elements, check selectionStart/selectionEnd + // (window.getSelection() doesn't work for form elements) + const target = e.target as HTMLInputElement | HTMLTextAreaElement; + hasSelection = + typeof target.selectionStart === "number" && + typeof target.selectionEnd === "number" && + target.selectionStart !== target.selectionEnd; + } else { + // For contentEditable and other elements, use window.getSelection() + hasSelection = (window.getSelection()?.toString().length ?? 0) > 0; + } if ((canInterrupt || showRetryBarrier) && (!inEditableElement || !hasSelection)) { e.preventDefault();