// SOS-TTS-Provider mit AsyncStorage-Persist + Listener-Pattern. // Live-Switch im SOS-Screen: Hook holt aktuelle Wahl + reagiert auf Änderungen // während des Mounts. Endpoint-Path wird beim Erzeugen der TTS-Queue gelesen. import AsyncStorage from '@react-native-async-storage/async-storage'; import { useEffect, useState } from 'react'; export type TtsProvider = 'openai' | 'gemini' | 'google-cloud' | 'elevenlabs' | 'cartesia'; const STORAGE_KEY = 'rebreak-sos-tts-provider'; const DEFAULT_PROVIDER: TtsProvider = 'openai'; export const TTS_PROVIDER_LABEL: Record = { openai: 'OpenAI', gemini: 'Gemini', 'google-cloud': 'Cloud', elevenlabs: 'ElevenLabs', cartesia: 'Cartesia', }; export const TTS_PROVIDER_ENDPOINT: Record = { openai: '/api/coach/speak-openai', gemini: '/api/coach/speak-gemini', 'google-cloud': '/api/coach/speak-google', elevenlabs: '/api/coach/speak-elevenlabs', cartesia: '/api/coach/speak-cartesia', }; const listeners = new Set<(p: TtsProvider) => void>(); let cached: TtsProvider | null = null; export async function loadTtsProvider(): Promise { if (cached) return cached; const raw = await AsyncStorage.getItem(STORAGE_KEY).catch(() => null); cached = raw === 'gemini' || raw === 'google-cloud' || raw === 'elevenlabs' || raw === 'cartesia' ? raw : DEFAULT_PROVIDER; return cached; } export async function setTtsProvider(p: TtsProvider): Promise { cached = p; await AsyncStorage.setItem(STORAGE_KEY, p).catch(() => {}); for (const cb of listeners) cb(p); } export function endpointForProvider(p: TtsProvider): string { return TTS_PROVIDER_ENDPOINT[p]; } /** Always-fresh read of the current provider — module-level `cached` is updated * synchronously inside `setTtsProvider` BEFORE listeners fire, so reading this * inside any async callback sidesteps React's state-update / useRef-update lag. */ export function currentProvider(): TtsProvider { return cached ?? DEFAULT_PROVIDER; } export function useTtsProvider(): [TtsProvider, (p: TtsProvider) => Promise] { const [p, setP] = useState(cached ?? DEFAULT_PROVIDER); useEffect(() => { let mounted = true; loadTtsProvider().then((v) => { if (mounted) setP(v); }); const cb = (v: TtsProvider) => { if (mounted) setP(v); }; listeners.add(cb); return () => { mounted = false; listeners.delete(cb); }; }, []); return [p, setTtsProvider]; }