diff --git a/client/src/components/Input/TextChat.jsx b/client/src/components/Input/TextChat.jsx index e35caca9cb..dba0639e89 100644 --- a/client/src/components/Input/TextChat.jsx +++ b/client/src/components/Input/TextChat.jsx @@ -29,6 +29,70 @@ export default function TextChat({ isSearchView = false }) { const isNotAppendable = latestMessage?.unfinished & !isSubmitting || latestMessage?.error; const { conversationId, jailbreak } = conversation || {}; + const [isSpeechSupported, setIsSpeechSupported] = useState(false); + const [isListening, setIsListening] = useState(false); + + useEffect(() => { + if ('SpeechRecognition' in window || 'webkitSpeechRecognition' in window) { + setIsSpeechSupported(true); + } else { + console.log("Browser does not support SpeechRecognition"); + setIsSpeechSupported(false); + return; + } + + if (!('SpeechRecognition' in window) && !('webkitSpeechRecognition' in window)) { + console.log("Browser does not support SpeechRecognition"); + return; + } + + const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition; + const recognition = new SpeechRecognition(); + + recognition.onstart = () => { + console.log("Speech recognition started"); + }; + + recognition.interimResults = true; + + recognition.onresult = (event) => { + let transcript = ''; + + for (let i = 0; i < event.results.length; i++) { + const result = event.results[i]; + transcript += result[0].transcript; + + if (result.isFinal) { + setText(transcript); + ask({ text: transcript }); + } + } + + // Set the text with both interim and final results + setText(transcript); + }; + + recognition.onend = () => { + setIsListening(false); + setText(''); + }; + + if (isListening) { + recognition.start(); + } else { + recognition.stop(); + } + + return () => { + recognition.stop(); + }; + }, [isListening]); + + const toggleListening = (e) => { + e.preventDefault(); + setIsListening((prevState) => !prevState); + }; + // auto focus to input, when enter a conversation. useEffect(() => { if (!conversationId) { @@ -177,6 +241,32 @@ export default function TextChat({ isSearchView = false }) { disabled={disabled || isNotAppendable} className="m-0 flex h-auto max-h-52 flex-1 resize-none overflow-auto border-0 bg-transparent p-0 pl-2 pr-12 leading-6 placeholder:text-sm placeholder:text-gray-600 focus:outline-none focus:ring-0 focus-visible:ring-0 dark:bg-transparent dark:placeholder:text-gray-500 md:pl-2" /> + {isSpeechSupported && ( + + + + + + + + {isListening && ( + + )} + + + + )}