diff --git a/src/lib/components/GlobalPlayer.svelte b/src/lib/components/GlobalPlayer.svelte index 2d14e59..83c8f74 100644 --- a/src/lib/components/GlobalPlayer.svelte +++ b/src/lib/components/GlobalPlayer.svelte @@ -61,13 +61,11 @@ pause: () => audioEl?.pause(), next: () => { next(); - syncAudioToCurrentTrack(); - void audioEl?.play(); + void syncAndAutoplay(); }, prev: () => { prev(currentTime); - syncAudioToCurrentTrack(); - void audioEl?.play(); + void syncAndAutoplay(); }, seekTo: (t) => { if (!audioEl) return; @@ -97,6 +95,35 @@ audioEl.volume = snap.volume; } + async function syncAndAutoplay() { + if (!audioEl) return; + + syncAudioToCurrentTrack(); + + // If the source changed, playback may not start immediately on some browsers + // until we wait for the new media to be ready. + if (audioEl.readyState < 2) { + await new Promise((resolve) => { + const el = audioEl; + if (!el) { + resolve(); + return; + } + const onCanPlay = () => { + el.removeEventListener("canplay", onCanPlay); + resolve(); + }; + el.addEventListener("canplay", onCanPlay, { once: true }); + }); + } + + try { + await audioEl.play(); + } catch { + // Autoplay may be blocked; user gesture will still allow manual play. + } + } + function onAudioPlay() { isPlaying = true; media.setPlaybackState("playing"); @@ -125,8 +152,7 @@ } function onAudioEnded() { next(); - syncAudioToCurrentTrack(); - if (snap.currentTrack) void audioEl?.play(); + void syncAndAutoplay(); } function formatTime(seconds: number) { @@ -222,8 +248,7 @@ disabled={!canPrev} onclick={() => { prev(currentTime); - syncAudioToCurrentTrack(); - void audioEl?.play(); + void syncAndAutoplay(); }} > Prev @@ -248,8 +273,7 @@ disabled={!canNext} onclick={() => { next(); - syncAudioToCurrentTrack(); - void audioEl?.play(); + void syncAndAutoplay(); }} > Next @@ -307,8 +331,7 @@ type="button" onclick={() => { jumpToTrack(t.id); - syncAudioToCurrentTrack(); - void audioEl?.play(); + void syncAndAutoplay(); }} > {#if snap.currentIndex === i} @@ -387,8 +410,7 @@ disabled={!canPrev} onclick={() => { prev(currentTime); - syncAudioToCurrentTrack(); - void audioEl?.play(); + void syncAndAutoplay(); }} > Prev @@ -413,8 +435,7 @@ disabled={!canNext} onclick={() => { next(); - syncAudioToCurrentTrack(); - void audioEl?.play(); + void syncAndAutoplay(); }} > Next @@ -455,8 +476,7 @@ type="button" onclick={() => { jumpToTrack(t.id); - syncAudioToCurrentTrack(); - void audioEl?.play(); + void syncAndAutoplay(); }} > {#if snap.currentIndex === i}