Files
SheetHappens/hooks/useVoice.ts
T

56 lines
1.5 KiB
TypeScript

import { useState, useCallback, useRef } from "react";
import {
ExpoSpeechRecognitionModule,
useSpeechRecognitionEvent,
} from "expo-speech-recognition";
export type VoiceState = "idle" | "listening" | "processing" | "error";
export function useVoice() {
const [state, setState] = useState<VoiceState>("idle");
const [transcript, setTranscript] = useState("");
const [error, setError] = useState<string | null>(null);
useSpeechRecognitionEvent("start", () => setState("listening"));
useSpeechRecognitionEvent("end", () => {
setState((s) => (s === "listening" ? "processing" : s));
});
useSpeechRecognitionEvent("result", (event) => {
const best = event.results[0]?.transcript ?? "";
setTranscript(best);
if (event.isFinal) setState("idle");
});
useSpeechRecognitionEvent("error", (event) => {
setError(event.error ?? "Voice recognition failed");
setState("error");
});
const start = useCallback(async (lang = "fr-FR") => {
setError(null);
setTranscript("");
const { granted } =
await ExpoSpeechRecognitionModule.requestPermissionsAsync();
if (!granted) {
setError("Microphone permission denied");
setState("error");
return;
}
ExpoSpeechRecognitionModule.start({ lang, interimResults: true });
}, []);
const stop = useCallback(() => {
ExpoSpeechRecognitionModule.stop();
}, []);
const reset = useCallback(() => {
setTranscript("");
setError(null);
setState("idle");
}, []);
return { state, transcript, error, start, stop, reset };
}