diff --git a/src/app/components/VoiceMessageRecorder.tsx b/src/app/components/VoiceMessageRecorder.tsx index db56a7812..3172de98f 100644 --- a/src/app/components/VoiceMessageRecorder.tsx +++ b/src/app/components/VoiceMessageRecorder.tsx @@ -383,7 +383,7 @@ export function VoiceMessageRecorder({ onSend, onError }: VoiceRecorderProps) { audio.pause(); setPreviewPlaying(false); } else { - audio.play(); + audio.play().catch(() => setPreviewPlaying(false)); setPreviewPlaying(true); } }} diff --git a/src/app/hooks/media/useMediaPlay.ts b/src/app/hooks/media/useMediaPlay.ts index 5ed61ad5f..6e4bacad9 100644 --- a/src/app/hooks/media/useMediaPlay.ts +++ b/src/app/hooks/media/useMediaPlay.ts @@ -17,7 +17,7 @@ export const useMediaPlay = ( (play: boolean) => { const targetEl = getTargetElement(); if (!targetEl) return; - if (play) targetEl.play(); + if (play) targetEl.play().catch(() => undefined); else targetEl.pause(); }, [getTargetElement], diff --git a/src/app/pages/client/ClientNonUIFeatures.tsx b/src/app/pages/client/ClientNonUIFeatures.tsx index ff1672824..73c464b69 100644 --- a/src/app/pages/client/ClientNonUIFeatures.tsx +++ b/src/app/pages/client/ClientNonUIFeatures.tsx @@ -259,7 +259,9 @@ function InviteNotifications() { const playSound = useCallback(() => { const audioElement = audioRef.current; - audioElement?.play(); + // Rejects under the autoplay policy until the user has interacted with the + // page (e.g. messages arriving right after launch); nothing to do then. + audioElement?.play().catch(() => undefined); }, []); // Arm once the client's initial sync has settled (+ a short grace so the async @@ -572,7 +574,9 @@ function MessageNotifications() { const playSound = useCallback(() => { const audioElement = audioRef.current; - audioElement?.play(); + // Rejects under the autoplay policy until the user has interacted with the + // page (e.g. messages arriving right after launch); nothing to do then. + audioElement?.play().catch(() => undefined); }, []); // Shared delivery tail for both the main timeline and per-thread paths: diff --git a/src/app/utils/dom.ts b/src/app/utils/dom.ts index a2d46242c..93c71c108 100644 --- a/src/app/utils/dom.ts +++ b/src/app/utils/dom.ts @@ -134,7 +134,9 @@ export const loadVideoElement = (url: string): Promise => video.src = url; video.load(); - video.play(); + // Only nudges the decoder toward the first frame; `onloadeddata` settles + // the promise, so an autoplay refusal here is harmless. + video.play().catch(() => undefined); }); export const getThumbnailDimensions = (width: number, height: number): [number, number] => {