diff --git a/public/app.js b/public/app.js index 2691ce6..b095a2c 100644 --- a/public/app.js +++ b/public/app.js @@ -288,6 +288,7 @@ const initApp = () => { // Variáveis de Reconhecimento de Voz let recognition = null; let isListening = false; + let lastInputWasVoice = false; // Rastrear se a última mensagem veio do microfone // ========================================================================== // THEME TOGGLE — Claro/Escuro @@ -488,13 +489,14 @@ const initApp = () => { }); // ========================================================================== - // VOZ — WEB SPEECH API (ditado) + // VOZ — WEB SPEECH API (ditado + conversa por voz) // ========================================================================== const initVoiceRecognition = () => { const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition; if (!SpeechRecognition) { btnVoice.style.display = 'none'; + console.warn('SpeechRecognition não suportado neste navegador.'); return; } @@ -509,6 +511,16 @@ const initApp = () => { userInput.value = transcript; userInput.dispatchEvent(new Event('input')); setVoiceState(false); + + // Marca que o input veio do microfone para auto-responder por voz + lastInputWasVoice = true; + + // Envia automaticamente a mensagem ditada + if (transcript.trim()) { + setTimeout(() => { + chatForm.dispatchEvent(new Event('submit', { cancelable: true })); + }, 300); + } }; recognition.onerror = (event) => { @@ -525,10 +537,10 @@ const initApp = () => { isListening = listening; if (listening) { btnVoice.classList.add('listening'); - btnVoice.setAttribute('title', 'Clique para parar'); + btnVoice.setAttribute('title', 'Clique para parar de ouvir'); } else { btnVoice.classList.remove('listening'); - btnVoice.setAttribute('title', 'Ditar mensagem'); + btnVoice.setAttribute('title', 'Conversar por voz'); } }; @@ -1685,6 +1697,15 @@ const initApp = () => { scrollToBottom(); + // AUTO-TTS: Se a mensagem veio do microfone, ler a resposta em voz alta automaticamente + if (lastInputWasVoice && assistantContent && !isMediaResponse) { + console.log('[VOZ] Mensagem veio do microfone — respondendo por voz automaticamente.'); + setTimeout(() => { + speakText(assistantContent, speakBtn); + }, 400); + } + lastInputWasVoice = false; + // Salvar resposta no estado e localStorage const assistantMsg = { role: 'assistant', content: assistantContent }; chat.messages.push(assistantMsg); diff --git a/public/style.css b/public/style.css index 878542e..a099863 100644 --- a/public/style.css +++ b/public/style.css @@ -1223,10 +1223,11 @@ code { .btn-voice { background: none !important; border: none !important; - color: var(--text-muted) !important; + color: var(--text-secondary, #a3a3a3) !important; border-radius: 50% !important; - width: 32px !important; - height: 32px !important; + width: 36px !important; + height: 36px !important; + min-width: 36px !important; display: flex; justify-content: center; align-items: center; @@ -1237,17 +1238,19 @@ code { } .btn-voice svg { - width: 18px; - height: 18px; + width: 20px; + height: 20px; } .btn-voice:hover { - color: var(--text-primary) !important; - transform: scale(1.05); + color: var(--brand-green, #10a37f) !important; + background-color: rgba(16, 163, 127, 0.1) !important; + transform: scale(1.1); } .btn-voice.listening { color: #ef4444 !important; + background-color: rgba(239, 68, 68, 0.12) !important; animation: pulse-voice 1.5s ease-in-out infinite; }