Fix TTS autoplay policy errors

- Handle NotAllowedError gracefully instead of showing alerts
- Make resume() async and catch playback errors
- Reset state properly when autoplay is blocked
- Clean up unused dependencies in playEdge callback

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Gemini Agent
2026-01-18 02:32:28 +00:00
parent d884e0d0bb
commit 883b0d7132

View File

@@ -181,9 +181,14 @@ export function useTTS({ settings, text }: UseTTSOptions): UseTTSReturn {
} catch (error) { } catch (error) {
console.error("Edge TTS error:", error); console.error("Edge TTS error:", error);
setIsLoading(false); setIsLoading(false);
// Don't show alert for autoplay policy errors - user just needs to click again
if (error instanceof DOMException && error.name === "NotAllowedError") {
console.log("Autoplay blocked - user needs to click play again");
return;
}
alert(error instanceof Error ? error.message : "Edge TTS failed"); alert(error instanceof Error ? error.message : "Edge TTS failed");
} }
}, [settings.edgeUrl, settings.speed, settings.voice]); }, [settings.speed]);
const playKokoro = useCallback(async () => { const playKokoro = useCallback(async () => {
setIsLoading(true); setIsLoading(true);
@@ -253,6 +258,11 @@ export function useTTS({ settings, text }: UseTTSOptions): UseTTSReturn {
} catch (error) { } catch (error) {
console.error("Kokoro TTS error:", error); console.error("Kokoro TTS error:", error);
setIsLoading(false); setIsLoading(false);
// Don't show alert for autoplay policy errors - user just needs to click again
if (error instanceof DOMException && error.name === "NotAllowedError") {
console.log("Autoplay blocked - user needs to click play again");
return;
}
alert(error instanceof Error ? error.message : "Kokoro TTS failed"); alert(error instanceof Error ? error.message : "Kokoro TTS failed");
} }
}, [settings.kokoroUrl, settings.speed]); }, [settings.kokoroUrl, settings.speed]);
@@ -277,13 +287,21 @@ export function useTTS({ settings, text }: UseTTSOptions): UseTTSReturn {
} }
}, [settings.engine]); }, [settings.engine]);
const resume = useCallback(() => { const resume = useCallback(async () => {
if (settings.engine === "browser") { if (settings.engine === "browser") {
speechSynthesis.resume(); speechSynthesis.resume();
setIsPaused(false); setIsPaused(false);
} else if (audioRef.current) { } else if (audioRef.current) {
audioRef.current.play(); try {
setIsPaused(false); await audioRef.current.play();
setIsPaused(false);
} catch (error) {
// Handle autoplay policy errors gracefully
console.error("Resume playback failed:", error);
// If autoplay was blocked, reset state so user can try again
setIsPaused(false);
setIsPlaying(false);
}
} }
}, [settings.engine]); }, [settings.engine]);