gemini will fix my track switching
This commit is contained in:
@@ -135,23 +135,7 @@
|
|||||||
// Scrubber is now driven by `bind:currentTime` on the <audio> element and
|
// Scrubber is now driven by `bind:currentTime` on the <audio> element and
|
||||||
// `bind:value={currentTime}` on the sliders, so we don't need explicit handlers.
|
// `bind:value={currentTime}` on the sliders, so we don't need explicit handlers.
|
||||||
|
|
||||||
function syncAudioToCurrentTrack() {
|
let isSrcChanging = $state(false);
|
||||||
if (!audioEl) return;
|
|
||||||
|
|
||||||
const track = snap.currentTrack;
|
|
||||||
if (!track) return;
|
|
||||||
|
|
||||||
const desired = track.src;
|
|
||||||
const desiredAbs = new URL(desired, window.location.href).href;
|
|
||||||
|
|
||||||
if (audioEl.currentSrc !== desiredAbs) {
|
|
||||||
audioEl.src = desired;
|
|
||||||
audioEl.load();
|
|
||||||
audioEl.currentTime = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
audioEl.volume = snap.volume;
|
|
||||||
}
|
|
||||||
|
|
||||||
function computeNextTrackToPreload(): Track | null {
|
function computeNextTrackToPreload(): Track | null {
|
||||||
// Prefer to preload the "linear next" item. For shuffle mode, we can still
|
// Prefer to preload the "linear next" item. For shuffle mode, we can still
|
||||||
@@ -202,22 +186,10 @@
|
|||||||
const el = audioEl;
|
const el = audioEl;
|
||||||
if (!el) return;
|
if (!el) return;
|
||||||
|
|
||||||
// Capture current src BEFORE syncing so we can detect changes reliably.
|
// If src is changing (set by $effect) or readyState is too low, wait until ready.
|
||||||
const beforeSrc = el.currentSrc;
|
// This is the key fix: it respects that the $effect is asynchronously loading media.
|
||||||
|
if (isSrcChanging || el.readyState < 3) {
|
||||||
syncAudioToCurrentTrack();
|
await waitForEvent(el, "canplay");
|
||||||
|
|
||||||
const afterSrc = el.currentSrc;
|
|
||||||
|
|
||||||
if (afterSrc !== beforeSrc) {
|
|
||||||
if (el.readyState < 1) {
|
|
||||||
await waitForEvent(el, "loadedmetadata");
|
|
||||||
}
|
|
||||||
if (el.readyState < 3) {
|
|
||||||
await waitForEvent(el, "canplay");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
await Promise.resolve();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -260,6 +232,7 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
function onAudioLoadedMetadata() {
|
function onAudioLoadedMetadata() {
|
||||||
|
isSrcChanging = false;
|
||||||
// `duration` is synced via `bind:duration` on <audio>.
|
// `duration` is synced via `bind:duration` on <audio>.
|
||||||
if (!audioEl) return;
|
if (!audioEl) return;
|
||||||
|
|
||||||
@@ -553,7 +526,26 @@
|
|||||||
if (!audioEl) return;
|
if (!audioEl) return;
|
||||||
|
|
||||||
audioEl.volume = snap.volume;
|
audioEl.volume = snap.volume;
|
||||||
syncAudioToCurrentTrack();
|
|
||||||
|
const track = snap.currentTrack;
|
||||||
|
if (!track) {
|
||||||
|
if (audioEl.src) {
|
||||||
|
audioEl.removeAttribute("src");
|
||||||
|
audioEl.load();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const desired = track.src;
|
||||||
|
const desiredAbs = new URL(desired, window.location.href).href;
|
||||||
|
|
||||||
|
// Use .src for a synchronous check. The .src property returns the resolved absolute URL.
|
||||||
|
if (audioEl.src !== desiredAbs) {
|
||||||
|
isSrcChanging = true;
|
||||||
|
audioEl.src = desired;
|
||||||
|
audioEl.load();
|
||||||
|
audioEl.currentTime = 0;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
|
|||||||
Reference in New Issue
Block a user