From 883b0d71329dbd0dd0b8921f39822f8e363ed5dc Mon Sep 17 00:00:00 2001 From: Gemini Agent Date: Sun, 18 Jan 2026 02:32:28 +0000 Subject: [PATCH] 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 --- src/hooks/useTTS.ts | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/src/hooks/useTTS.ts b/src/hooks/useTTS.ts index 52d9d94..86e0a65 100644 --- a/src/hooks/useTTS.ts +++ b/src/hooks/useTTS.ts @@ -181,9 +181,14 @@ export function useTTS({ settings, text }: UseTTSOptions): UseTTSReturn { } catch (error) { console.error("Edge TTS error:", error); 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"); } - }, [settings.edgeUrl, settings.speed, settings.voice]); + }, [settings.speed]); const playKokoro = useCallback(async () => { setIsLoading(true); @@ -253,6 +258,11 @@ export function useTTS({ settings, text }: UseTTSOptions): UseTTSReturn { } catch (error) { console.error("Kokoro TTS error:", error); 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"); } }, [settings.kokoroUrl, settings.speed]); @@ -277,13 +287,21 @@ export function useTTS({ settings, text }: UseTTSOptions): UseTTSReturn { } }, [settings.engine]); - const resume = useCallback(() => { + const resume = useCallback(async () => { if (settings.engine === "browser") { speechSynthesis.resume(); setIsPaused(false); } else if (audioRef.current) { - audioRef.current.play(); - setIsPaused(false); + try { + 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]);