added visual waiting steps
All checks were successful
Deploy FluentGerman.ai / deploy (push) Successful in 52s

This commit is contained in:
2026-02-18 12:47:58 +01:00
parent 557b7c28aa
commit 829238dd2f
2 changed files with 7 additions and 5 deletions

View File

@@ -160,7 +160,6 @@ document.addEventListener('DOMContentLoaded', async () => {
const text = inputEl.value.trim(); const text = inputEl.value.trim();
if (!text) return; if (!text) return;
const wasVoice = voice.lastInputWasVoice;
voice.lastInputWasVoice = false; voice.lastInputWasVoice = false;
inputEl.value = ''; inputEl.value = '';
@@ -169,7 +168,7 @@ document.addEventListener('DOMContentLoaded', async () => {
appendMessage('user', text); appendMessage('user', text);
history.push({ role: 'user', content: text }); history.push({ role: 'user', content: text });
const assistantEl = appendMessage('assistant', ''); const assistantEl = appendMessage('assistant', voiceModeOn ? 'Thinking...' : '');
let fullResponse = ''; let fullResponse = '';
try { try {
@@ -188,9 +187,7 @@ document.addEventListener('DOMContentLoaded', async () => {
// Special handling for Voice Mode: Buffer text, wait for TTS, then show & play // Special handling for Voice Mode: Buffer text, wait for TTS, then show & play
if (voiceModeOn) { if (voiceModeOn) {
// Show thinking state // "Thinking..." is already shown from appendMessage above
assistantEl.innerHTML = '<span class="thinking-dots">Thinking<span>.</span><span>.</span><span>.</span></span>';
assistantEl.classList.add('message-thinking');
while (true) { while (true) {
const { done, value } = await reader.read(); const { done, value } = await reader.read();

View File

@@ -147,6 +147,8 @@ class VoiceManager {
stopRecording() { stopRecording() {
if (this.mode === 'api') { if (this.mode === 'api') {
if (this.mediaRecorder?.state === 'recording') { if (this.mediaRecorder?.state === 'recording') {
// Show processing state immediately (don't wait for onstop callback)
if (this.onProcessing) this.onProcessing(true);
this.mediaRecorder.stop(); this.mediaRecorder.stop();
} else { } else {
this.isRecording = false; this.isRecording = false;
@@ -240,17 +242,20 @@ class VoiceManager {
return new Promise(resolve => { return new Promise(resolve => {
audio.onended = () => { audio.onended = () => {
if (avatarContainer) avatarContainer.classList.remove('speaking'); if (avatarContainer) avatarContainer.classList.remove('speaking');
URL.revokeObjectURL(audioUrl);
resolve(); resolve();
}; };
// Handle errors during playback (e.g. format issues) // Handle errors during playback (e.g. format issues)
audio.onerror = () => { audio.onerror = () => {
if (avatarContainer) avatarContainer.classList.remove('speaking'); if (avatarContainer) avatarContainer.classList.remove('speaking');
URL.revokeObjectURL(audioUrl);
resolve(); resolve();
} }
}); });
} catch (e) { } catch (e) {
console.error("Playback failed", e); console.error("Playback failed", e);
if (avatarContainer) avatarContainer.classList.remove('speaking'); if (avatarContainer) avatarContainer.classList.remove('speaking');
URL.revokeObjectURL(audioUrl);
} }
} }