import { useState, useEffect, useRef, useCallback } from 'react'; import { Platform } from 'react-native'; export interface UseSpeechRecognitionReturn { isListening: boolean; recognizedText: string; startListening: (options?: { continuous?: boolean }) => Promise; stopListening: () => void; isAvailable: boolean; hasPermission: boolean; requestPermission: () => Promise; } export function useSpeechRecognition(): UseSpeechRecognitionReturn { const [isListening, setIsListening] = useState(false); const [recognizedText, setRecognizedText] = useState(''); const [isAvailable, setIsAvailable] = useState(false); const recognitionRef = useRef(null); useEffect(() => { if (typeof window !== 'undefined') { const SpeechRecognition = (window as any).SpeechRecognition || (window as any).webkitSpeechRecognition; if (SpeechRecognition) { setIsAvailable(true); const recognition = new SpeechRecognition(); recognition.continuous = false; // Default recognition.interimResults = true; recognition.lang = 'en-US'; recognition.onstart = () => { setIsListening(true); }; recognition.onend = () => { setIsListening(false); }; recognition.onresult = (event: any) => { const transcript = Array.from(event.results) .map((result: any) => result[0]) .map((result: any) => result.transcript) .join(''); setRecognizedText(transcript); }; recognition.onerror = (event: any) => { setIsListening(false); }; recognitionRef.current = recognition; } } }, []); const requestPermission = async () => { // Web API usually requests permission on start(), but we can return true if available return isAvailable; }; const startListening = async (options?: { continuous?: boolean }) => { if (!recognitionRef.current) return; try { recognitionRef.current.continuous = options?.continuous ?? false; setRecognizedText(''); recognitionRef.current.start(); } catch (e) { setIsListening(false); } }; const stopListening = () => { if (recognitionRef.current) { recognitionRef.current.stop(); } }; return { isListening, recognizedText, startListening, stopListening, isAvailable, hasPermission: isAvailable, // Assume permission handled by browser requestPermission }; }