60 lines
1.3 KiB
TypeScript
60 lines
1.3 KiB
TypeScript
import { useState, useEffect, useCallback } from 'react';
|
|
import {
|
|
initializeSherpaTTS,
|
|
speak,
|
|
stop,
|
|
isAvailable,
|
|
addStateListener,
|
|
getState,
|
|
type PiperVoice,
|
|
} from '@/services/sherpaTTS';
|
|
|
|
interface TTSState {
|
|
initialized: boolean;
|
|
initializing: boolean;
|
|
error: string | null;
|
|
isSpeaking: boolean;
|
|
}
|
|
|
|
export function useTTS() {
|
|
const [state, setState] = useState<TTSState>({
|
|
...getState(),
|
|
isSpeaking: false,
|
|
});
|
|
|
|
useEffect(() => {
|
|
const unsubscribe = addStateListener((newState) => {
|
|
setState((prev) => ({
|
|
...prev,
|
|
...newState,
|
|
}));
|
|
});
|
|
|
|
// In Expo Go mode, don't try to initialize (stub always returns false)
|
|
// This is handled by the stub in sherpaTTS.ts
|
|
|
|
return unsubscribe;
|
|
}, []);
|
|
|
|
const speakText = useCallback(
|
|
async (text: string, options?: { speed?: number; speakerId?: number }) => {
|
|
// Always return false in Expo Go mode - voice.tsx will use expo-speech instead
|
|
console.log('[useTTS] Sherpa TTS not available in Expo Go');
|
|
return;
|
|
},
|
|
[]
|
|
);
|
|
|
|
const stopSpeaking = useCallback(() => {
|
|
stop();
|
|
setState((prev) => ({ ...prev, isSpeaking: false }));
|
|
}, []);
|
|
|
|
return {
|
|
...state,
|
|
isReady: false, // Always false in Expo Go mode
|
|
speak: speakText,
|
|
stop: stopSpeaking,
|
|
};
|
|
}
|