From 2df0848fc8373c95ee3ace1b19bce46ee60a6052 Mon Sep 17 00:00:00 2001 From: anish Date: Fri, 22 Aug 2025 08:13:44 +0100 Subject: [PATCH] fix: allow audio to play in background on iOS (#58) --- src/components/sounds/sound/sound.tsx | 8 +++++++- src/helpers/browser-detect.ts | 13 ++++++++++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/components/sounds/sound/sound.tsx b/src/components/sounds/sound/sound.tsx index 8ba190f..99e4a33 100644 --- a/src/components/sounds/sound/sound.tsx +++ b/src/components/sounds/sound/sound.tsx @@ -14,6 +14,7 @@ import styles from './sound.module.css'; import type { Sound as SoundType } from '@/data/types'; import { useKeyboardButton } from '@/hooks/use-keyboard-button'; +import { BrowserDetect } from '@/helpers/browser-detect'; interface SoundProps extends SoundType { functional: boolean; @@ -43,7 +44,12 @@ export const Sound = forwardRef(function Sound( const isLoading = useLoadingStore(state => state.loaders[src]); - const sound = useSound(src, { loop: true, volume: adjustedVolume }); + const sound = useSound( + src, + { loop: true, volume: adjustedVolume }, + BrowserDetect.isIOS() + ); + useEffect(() => { if (locked) return; diff --git a/src/helpers/browser-detect.ts b/src/helpers/browser-detect.ts index 3d47ba1..118ea29 100644 --- a/src/helpers/browser-detect.ts +++ b/src/helpers/browser-detect.ts @@ -1,11 +1,12 @@ export class BrowserDetect { private static _isSafari: boolean | undefined; + private static _isIOS: boolean | undefined; public static isSafari(): boolean { if (typeof BrowserDetect._isSafari !== 'undefined') { return BrowserDetect._isSafari; } - + // Source: https://github.com/goldfire/howler.js/blob/v2.2.4/src/howler.core.js#L270 BrowserDetect._isSafari = navigator.userAgent.indexOf('Safari') !== -1 && @@ -13,4 +14,14 @@ export class BrowserDetect { return BrowserDetect._isSafari; } + + /** True on iPhone/iPad/iPod (covers iPadOS-on-Mac UA quirk). */ + public static isIOS(): boolean { + if (typeof BrowserDetect._isIOS !== 'undefined') return BrowserDetect._isIOS; + if (typeof navigator === 'undefined') return false; + const ua = navigator.userAgent || ''; + const touchMac = /\bMacintosh\b/.test(ua) && 'ontouchend' in (window as any); + BrowserDetect._isIOS = /\b(iPad|iPhone|iPod)\b/i.test(ua) || touchMac; + return BrowserDetect._isIOS; + } }