From e14f245586226ba5e3fabc2d8adee188ca7cd919 Mon Sep 17 00:00:00 2001 From: Classic298 <27028174+Classic298@users.noreply.github.com> Date: Thu, 24 Sep 2026 05:55:21 +0200 Subject: [PATCH] fix: keep the M mute shortcut working during voice calls (#30421) In voice mode, pressing M after a turn typed an "m" into the chat box instead of muting. After each voice message the chat input pulled keyboard focus back to itself, and the call overlay ignores M while focus is in a text field so typing still works. The chat input now leaves focus alone while a call is open: clearing it after a send, the remount on the first message of a new chat and the editor's autofocus all skip focusing during a call. Clicking into the box and typing during a call still works, and outside a call the input focuses exactly as before. Checked in a browser with a fake microphone: M mutes after the first, second and third turn, in new and existing chats; "m" typed into a focused input during a call still types. Fixes #30406 --- src/lib/components/chat/MessageInput.svelte | 6 ++++-- src/lib/components/common/RichTextInput.svelte | 13 +++++++++---- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/lib/components/chat/MessageInput.svelte b/src/lib/components/chat/MessageInput.svelte index e6b746e3d3..5c5c67cca2 100644 --- a/src/lib/components/chat/MessageInput.svelte +++ b/src/lib/components/chat/MessageInput.svelte @@ -1588,8 +1588,10 @@ loaded = true; window.setTimeout(() => { - const chatInput = document.getElementById('chat-input'); - chatInput?.focus(); + if (!$showCallOverlay) { + const chatInput = document.getElementById('chat-input'); + chatInput?.focus(); + } }, 0); window.addEventListener('keydown', onKeyDown); diff --git a/src/lib/components/common/RichTextInput.svelte b/src/lib/components/common/RichTextInput.svelte index 5e4f5b1d90..7ddf962af4 100644 --- a/src/lib/components/common/RichTextInput.svelte +++ b/src/lib/components/common/RichTextInput.svelte @@ -2,7 +2,7 @@ import { marked } from 'marked'; import DOMPurify from 'dompurify'; import equal from 'fast-deep-equal'; - import { skills, terminalSkills } from '$lib/stores'; + import { showCallOverlay, skills, terminalSkills } from '$lib/stores'; marked.use({ breaks: true, @@ -346,6 +346,9 @@ export let insertPromptAsRichText = false; export let floatingMenuPlacement = 'bottom-start'; + // Keep focus off the chat input during a call so the call overlay's M shortcut works + $: suppressAutoFocus = messageInput && $showCallOverlay; + let content = null; let htmlValue = ''; let jsonValue = ''; @@ -550,7 +553,9 @@ selectNextTemplate(editor.view.state, editor.view.dispatch); // Ensure the editor is still valid before trying to focus - focus(); + if (!suppressAutoFocus) { + focus(); + } }; export const insertContent = (content) => { @@ -710,7 +715,7 @@ // After updating the state, try to find and select the next template setTimeout(() => { const templateFound = selectNextTemplate(editor.view.state, editor.view.dispatch); - if (!templateFound) { + if (!templateFound && !suppressAutoFocus) { editor.commands.focus('end'); } }, 0); @@ -945,7 +950,7 @@ ...(collaboration && provider ? [provider.getEditorExtension()] : []) ], content: provider ? undefined : content, - autofocus: messageInput ? true : false, + autofocus: messageInput && !$showCallOverlay, onTransaction: () => { if (!editor) return;