FinMK / frontend /src /components /ChatVoiceButton.jsx
Kumar
Refactor: Exclude PDF and CSV files from Git to fix HF push error
24e6f5b
import { useState, useRef, useEffect } from 'react';
import { Mic, MicOff } from 'lucide-react';
const ChatVoiceButton = ({ onInput }) => {
const [isListening, setIsListening] = useState(false);
const recognitionRef = useRef(null);
const silenceTimerRef = useRef(null);
const stopSilenceTimer = () => {
if (silenceTimerRef.current) {
clearTimeout(silenceTimerRef.current);
silenceTimerRef.current = null;
}
};
const startSilenceTimer = () => {
stopSilenceTimer();
silenceTimerRef.current = setTimeout(() => {
console.log("Chat Silence timeout. Stopping.");
if (recognitionRef.current) recognitionRef.current.stop();
}, 6000); // 6 seconds of silence
};
const onInputRef = useRef(onInput);
useEffect(() => {
onInputRef.current = onInput;
}, [onInput]);
useEffect(() => {
if ('webkitSpeechRecognition' in window || 'SpeechRecognition' in window) {
const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
recognitionRef.current = new SpeechRecognition();
recognitionRef.current.continuous = true;
recognitionRef.current.interimResults = true;
recognitionRef.current.lang = 'en-US';
recognitionRef.current.onstart = () => {
setIsListening(true);
startSilenceTimer();
};
recognitionRef.current.onend = () => {
setIsListening(false);
stopSilenceTimer();
};
recognitionRef.current.onerror = (event) => {
console.error("Speech recognition error", event.error);
setIsListening(false);
stopSilenceTimer();
};
recognitionRef.current.onresult = (event) => {
startSilenceTimer(); // Reset timer on every result
let finalTranscript = '';
let interimTranscript = '';
for (let i = event.resultIndex; i < event.results.length; ++i) {
if (event.results[i].isFinal) {
finalTranscript += event.results[i][0].transcript;
} else {
interimTranscript += event.results[i][0].transcript;
}
}
if (onInputRef.current) {
onInputRef.current(finalTranscript || interimTranscript, event.results[event.results.length - 1].isFinal);
}
};
}
return () => {
if (recognitionRef.current) recognitionRef.current.stop();
stopSilenceTimer();
};
}, []);
const toggleListening = () => {
if (!recognitionRef.current) {
alert("Voice not supported in this browser.");
return;
}
if (isListening) {
recognitionRef.current.stop();
} else {
recognitionRef.current.start();
}
};
return (
<button
onClick={toggleListening}
title="Voice Input"
style={{
background: isListening ? 'rgba(239, 68, 68, 0.2)' : 'transparent',
color: isListening ? '#ef4444' : 'rgba(255,255,255,0.5)',
border: isListening ? '1px solid #ef4444' : 'none',
width: '36px', height: '36px',
borderRadius: '50%',
display: 'flex', alignItems: 'center', justifyContent: 'center',
cursor: 'pointer',
transition: 'all 0.2s',
marginRight: '0.5rem'
}}
>
{isListening ? <MicOff size={18} /> : <Mic size={18} />}
</button>
);
};
export default ChatVoiceButton;