Initial scaffold: Expo SDK 56, expo-router, expo-sqlite, NativeWind
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
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 };
|
||||
}
|
||||
Reference in New Issue
Block a user