diff --git a/app/components/chat/BaseChat.tsx b/app/components/chat/BaseChat.tsx index 902cb23..fee28c0 100644 --- a/app/components/chat/BaseChat.tsx +++ b/app/components/chat/BaseChat.tsx @@ -87,6 +87,35 @@ interface BaseChatProps { enhancePrompt?: () => void; } +const SpeechRecognitionButton = ({ + isListening, + onStart, + onStop, + disabled +}: { + isListening: boolean; + onStart: () => void; + onStop: () => void; + disabled: boolean; +}) => { + return ( + + {isListening ? ( +
+ ) : ( +
+ )} + + ); +}; + export const BaseChat = React.forwardRef( ( { @@ -114,6 +143,8 @@ export const BaseChat = React.forwardRef( const TEXTAREA_MAX_HEIGHT = chatStarted ? 400 : 200; const [apiKeys, setApiKeys] = useState>({}); const [modelList, setModelList] = useState(MODEL_LIST); + const [isListening, setIsListening] = useState(false); + const [recognition, setRecognition] = useState(null); useEffect(() => { // Load API keys from cookies on component mount @@ -134,8 +165,49 @@ export const BaseChat = React.forwardRef( initializeModelList().then((modelList) => { setModelList(modelList); }); + if (typeof window !== 'undefined' && ('SpeechRecognition' in window || 'webkitSpeechRecognition' in window)) { + const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition; + const recognition = new SpeechRecognition(); + recognition.continuous = true; + recognition.interimResults = true; + + recognition.onresult = (event) => { + const transcript = Array.from(event.results) + .map(result => result[0]) + .map(result => result.transcript) + .join(''); + + if (handleInputChange) { + const syntheticEvent = { + target: { value: transcript }, + } as React.ChangeEvent; + handleInputChange(syntheticEvent); + } + }; + + recognition.onerror = (event) => { + console.error('Speech recognition error:', event.error); + setIsListening(false); + }; + + setRecognition(recognition); + } }, []); + const startListening = () => { + if (recognition) { + recognition.start(); + setIsListening(true); + } + }; + + const stopListening = () => { + if (recognition) { + recognition.stop(); + setIsListening(false); + } + }; + const updateApiKey = (provider: string, key: string) => { try { const updatedApiKeys = { ...apiKeys, [provider]: key }; @@ -284,6 +356,13 @@ export const BaseChat = React.forwardRef( )} + +
{input.length > 3 ? (
diff --git a/app/types/global.d.ts b/app/types/global.d.ts index a1f6789..193c65d 100644 --- a/app/types/global.d.ts +++ b/app/types/global.d.ts @@ -1,3 +1,5 @@ interface Window { showDirectoryPicker(): Promise; + webkitSpeechRecognition: typeof SpeechRecognition; + SpeechRecognition: typeof SpeechRecognition; }