mirror of
https://github.com/remvze/moodist.git
synced 2025-12-18 09:24:14 +00:00
fix: wip for ios
This commit is contained in:
parent
699f49bfa3
commit
54b46123b4
1 changed files with 65 additions and 0 deletions
|
|
@ -20,6 +20,58 @@ import { FADE_OUT } from '@/constants/events';
|
|||
import type { Sound } from '@/data/types';
|
||||
import { subscribe } from '@/lib/event';
|
||||
|
||||
/**
|
||||
* =========================================
|
||||
*/
|
||||
declare global {
|
||||
interface Window {
|
||||
__howlerStreamPatched?: boolean;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Patches Howler's master gain node to stream its output into a hidden HTML audio element.
|
||||
* This helps prevent iOS from suspending audio when the app goes into the background.
|
||||
*/
|
||||
export function setupAudioStream(): void {
|
||||
if (
|
||||
typeof window !== 'undefined' &&
|
||||
Howler.ctx &&
|
||||
!window.__howlerStreamPatched
|
||||
) {
|
||||
const audioCtx = Howler.ctx;
|
||||
const masterGain = Howler.masterGain;
|
||||
|
||||
// Create a MediaStream destination node to capture the AudioContext output.
|
||||
const streamDestination = audioCtx.createMediaStreamDestination();
|
||||
|
||||
// Disconnect the master gain from its default destination.
|
||||
masterGain.disconnect();
|
||||
|
||||
// Reconnect the master gain to both the default destination and the stream destination.
|
||||
masterGain.connect(audioCtx.destination);
|
||||
masterGain.connect(streamDestination);
|
||||
|
||||
// Create a hidden HTML audio element to play the captured stream.
|
||||
const audioElement = document.createElement('audio');
|
||||
audioElement.setAttribute('playsinline', 'true'); // essential for iOS
|
||||
audioElement.srcObject = streamDestination.stream;
|
||||
audioElement.style.display = 'none';
|
||||
document.body.appendChild(audioElement);
|
||||
|
||||
// Attempt to play the audio element. Note that iOS requires a user gesture.
|
||||
audioElement.play().catch((err: unknown) => {
|
||||
console.error('Failed to play background stream:', err);
|
||||
});
|
||||
|
||||
// Mark the stream as patched so we don’t run this code again.
|
||||
window.__howlerStreamPatched = true;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* =========================================
|
||||
*/
|
||||
|
||||
export function App() {
|
||||
const categories = useMemo(() => sounds.categories, []);
|
||||
|
||||
|
|
@ -86,6 +138,19 @@ export function App() {
|
|||
return [...favorites, ...categories];
|
||||
}, [favoriteSounds, categories]);
|
||||
|
||||
useEffect(() => {
|
||||
const handleUserInteraction = () => {
|
||||
setupAudioStream();
|
||||
document.removeEventListener('click', handleUserInteraction);
|
||||
};
|
||||
|
||||
document.addEventListener('click', handleUserInteraction);
|
||||
|
||||
return () => {
|
||||
document.removeEventListener('click', handleUserInteraction);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<SnackbarProvider>
|
||||
<StoreConsumer>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue