WIP: global player pt. 6 fix playback finally

This commit is contained in:
2026-02-10 00:22:52 -08:00
parent cfd45b6815
commit c8de948e7f
3 changed files with 32 additions and 15 deletions

View File

@@ -9,7 +9,25 @@
const audio = getAudioContext(); const audio = getAudioContext();
// Local state for slider to allow binding
let sliderValue = $state([0]);
// Sync Audio -> Slider
$effect(() => {
// Only sync if the value is different to avoid unnecessary updates
// and potential loops if onValueChange fires on prop change.
// Using a small threshold or just direct assignment if we trust the loop break.
if (Math.abs(sliderValue[0] - audio.currentTime) > 0.1) {
sliderValue = [audio.currentTime];
}
});
function onSeek(v: number[]) { function onSeek(v: number[]) {
// Guard against feedback loop:
// If the value matches current time (within tolerance), it's likely a feedback
// from the effect above -> component -> onValueChange.
if (Math.abs(v[0] - audio.currentTime) < 0.1) return;
audio.seek(v[0]); audio.seek(v[0]);
} }
@@ -55,9 +73,9 @@
<!-- Progress --> <!-- Progress -->
<div class="space-y-2"> <div class="space-y-2">
<Slider <Slider
value={[audio.currentTime]} bind:value={sliderValue}
max={audio.duration || 100} max={audio.duration || 100}
step={1} step={0.01}
onValueChange={onSeek} onValueChange={onSeek}
type="multiple" type="multiple"
class="w-full" class="w-full"

View File

@@ -11,8 +11,17 @@
const audio = getAudioContext(); const audio = getAudioContext();
let open = $state(false); let open = $state(false);
let sliderValue = $state([0]);
// Sync Audio -> Slider
$effect(() => {
if (Math.abs(sliderValue[0] - audio.currentTime) > 0.1) {
sliderValue = [audio.currentTime];
}
});
function onSeek(v: number[]) { function onSeek(v: number[]) {
if (Math.abs(v[0] - audio.currentTime) < 0.1) return;
audio.seek(v[0]); audio.seek(v[0]);
} }
</script> </script>
@@ -101,9 +110,9 @@
<!-- Progress --> <!-- Progress -->
<div class="space-y-2"> <div class="space-y-2">
<Slider <Slider
value={[audio.currentTime]} bind:value={sliderValue}
max={audio.duration || 100} max={audio.duration || 100}
step={1} step={0.01}
onValueChange={onSeek} onValueChange={onSeek}
type="multiple" type="multiple"
class="w-full" class="w-full"

View File

@@ -16,7 +16,6 @@
// ... existing imports ... // ... existing imports ...
onMount(() => { onMount(() => {
console.log("PlayerRoot mounted");
audioCtx.setElement(audioEl); audioCtx.setElement(audioEl);
// Load state // Load state
@@ -37,10 +36,6 @@
// ... existing effect for playback ... // ... existing effect for playback ...
$effect(() => { $effect(() => {
const track = player.currentTrack; const track = player.currentTrack;
console.log("Playback effect triggered", {
trackId: track?.id,
src: track?.src,
});
if (audioEl) { if (audioEl) {
if (track) { if (track) {
const newSrc = track.src; const newSrc = track.src;
@@ -49,14 +44,9 @@
// audioEl.src sets the attribute, currentSrc is the resolved URL // audioEl.src sets the attribute, currentSrc is the resolved URL
const newSrcAbsolute = new URL(newSrc, document.baseURI).href; const newSrcAbsolute = new URL(newSrc, document.baseURI).href;
console.log("Src check", { // audioEl.src sets the attribute, currentSrc is the resolved URL
currentSrc,
newSrcAbsolute,
match: currentSrc === newSrcAbsolute,
});
if (currentSrc !== newSrcAbsolute) { if (currentSrc !== newSrcAbsolute) {
console.log("Setting new src", newSrc);
audioEl.src = newSrc; audioEl.src = newSrc;
audioEl.play().catch((e) => { audioEl.play().catch((e) => {
console.warn("Autoplay blocked or failed", e); console.warn("Autoplay blocked or failed", e);