🎤 Voz + ⌨️ Atalhos: Ctrl+N/F/K, Escape, microfone com Web Speech API

This commit is contained in:
2026-05-25 23:25:36 +00:00
parent c935e980b2
commit 4edd3fce7d
3 changed files with 129 additions and 0 deletions
+85
View File
@@ -64,6 +64,7 @@ document.addEventListener('DOMContentLoaded', () => {
const userInput = document.getElementById('userInput');
const btnSend = document.getElementById('btnSend');
const btnVoice = document.getElementById('btnVoice');
const chatForm = document.getElementById('chatForm');
const messagesContainer = document.getElementById('messagesContainer');
const welcomeContainer = document.getElementById('welcomeContainer');
@@ -90,6 +91,10 @@ document.addEventListener('DOMContentLoaded', () => {
let searchQuery = '';
let activeTag = 'all';
// Variáveis de Reconhecimento de Voz
let recognition = null;
let isListening = false;
// ==========================================================================
// CONTROLES DE INTERFACE & SIDEBAR
// ==========================================================================
@@ -156,6 +161,83 @@ document.addEventListener('DOMContentLoaded', () => {
renderHistory();
});
// ==========================================================================
// VOZ — WEB SPEECH API (ditado)
// ==========================================================================
const initVoiceRecognition = () => {
const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
if (!SpeechRecognition) {
btnVoice.style.display = 'none';
return;
}
recognition = new SpeechRecognition();
recognition.lang = 'pt-BR';
recognition.continuous = false;
recognition.interimResults = false;
recognition.maxAlternatives = 1;
recognition.onresult = (event) => {
const transcript = event.results[0][0].transcript;
userInput.value = transcript;
userInput.dispatchEvent(new Event('input'));
setVoiceState(false);
};
recognition.onerror = (event) => {
console.warn('Voice error:', event.error);
setVoiceState(false);
};
recognition.onend = () => {
setVoiceState(false);
};
};
const setVoiceState = (listening) => {
isListening = listening;
if (listening) {
btnVoice.classList.add('listening');
btnVoice.setAttribute('title', 'Clique para parar');
} else {
btnVoice.classList.remove('listening');
btnVoice.setAttribute('title', 'Ditar mensagem');
}
};
btnVoice.addEventListener('click', () => {
if (!recognition) return;
if (isListening) {
recognition.stop();
} else {
recognition.start();
setVoiceState(true);
}
});
// ==========================================================================
// ATALHOS DE TECLADO
// ==========================================================================
document.addEventListener('keydown', (e) => {
// Ctrl+N → novo chat
if ((e.ctrlKey || e.metaKey) && e.key === 'n') {
e.preventDefault();
createNewChat();
}
// Ctrl+F ou Ctrl+K → focar busca
if ((e.ctrlKey || e.metaKey) && (e.key === 'f' || e.key === 'k')) {
e.preventDefault();
toggleSidebar(true);
setTimeout(() => searchInput.focus(), 50);
}
// Escape → fechar sidebar
if (e.key === 'Escape') {
toggleSidebar(false);
}
});
// ==========================================================================
// HISTÓRICO DE CHATS (LOCALSTORAGE) — VERSÃO COMPLETA COM PINNED, TAGS, BUSCA
// ==========================================================================
@@ -682,4 +764,7 @@ document.addEventListener('DOMContentLoaded', () => {
} else {
createNewChat();
}
// Inicializar reconhecimento de voz
initVoiceRecognition();
});