From 829238dd2fcb63320505a7542be6dbfb702ee260 Mon Sep 17 00:00:00 2001 From: Dennis Thiessen Date: Wed, 18 Feb 2026 12:47:58 +0100 Subject: [PATCH] added visual waiting steps --- frontend/js/chat.js | 7 ++----- frontend/js/voice.js | 5 +++++ 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/frontend/js/chat.js b/frontend/js/chat.js index 8954c77..54ec0cd 100644 --- a/frontend/js/chat.js +++ b/frontend/js/chat.js @@ -160,7 +160,6 @@ document.addEventListener('DOMContentLoaded', async () => { const text = inputEl.value.trim(); if (!text) return; - const wasVoice = voice.lastInputWasVoice; voice.lastInputWasVoice = false; inputEl.value = ''; @@ -169,7 +168,7 @@ document.addEventListener('DOMContentLoaded', async () => { appendMessage('user', text); history.push({ role: 'user', content: text }); - const assistantEl = appendMessage('assistant', ''); + const assistantEl = appendMessage('assistant', voiceModeOn ? 'Thinking...' : ''); let fullResponse = ''; try { @@ -188,9 +187,7 @@ document.addEventListener('DOMContentLoaded', async () => { // Special handling for Voice Mode: Buffer text, wait for TTS, then show & play if (voiceModeOn) { - // Show thinking state - assistantEl.innerHTML = 'Thinking...'; - assistantEl.classList.add('message-thinking'); + // "Thinking..." is already shown from appendMessage above while (true) { const { done, value } = await reader.read(); diff --git a/frontend/js/voice.js b/frontend/js/voice.js index 4d0bea2..0c2b0b5 100644 --- a/frontend/js/voice.js +++ b/frontend/js/voice.js @@ -147,6 +147,8 @@ class VoiceManager { stopRecording() { if (this.mode === 'api') { if (this.mediaRecorder?.state === 'recording') { + // Show processing state immediately (don't wait for onstop callback) + if (this.onProcessing) this.onProcessing(true); this.mediaRecorder.stop(); } else { this.isRecording = false; @@ -240,17 +242,20 @@ class VoiceManager { return new Promise(resolve => { audio.onended = () => { if (avatarContainer) avatarContainer.classList.remove('speaking'); + URL.revokeObjectURL(audioUrl); resolve(); }; // Handle errors during playback (e.g. format issues) audio.onerror = () => { if (avatarContainer) avatarContainer.classList.remove('speaking'); + URL.revokeObjectURL(audioUrl); resolve(); } }); } catch (e) { console.error("Playback failed", e); if (avatarContainer) avatarContainer.classList.remove('speaking'); + URL.revokeObjectURL(audioUrl); } }