WIP: global player pt. 5 svelte bindings
This commit is contained in:
@@ -16,6 +16,7 @@
|
||||
// ... existing imports ...
|
||||
|
||||
onMount(() => {
|
||||
console.log("PlayerRoot mounted");
|
||||
audioCtx.setElement(audioEl);
|
||||
|
||||
// Load state
|
||||
@@ -25,56 +26,21 @@
|
||||
}
|
||||
|
||||
// Setup MediaSession
|
||||
if ("mediaSession" in navigator) {
|
||||
navigator.mediaSession.setActionHandler("play", () => {
|
||||
audioCtx.paused = false;
|
||||
});
|
||||
navigator.mediaSession.setActionHandler("pause", () => {
|
||||
audioCtx.paused = true;
|
||||
});
|
||||
navigator.mediaSession.setActionHandler("previoustrack", () =>
|
||||
player.prev(),
|
||||
);
|
||||
navigator.mediaSession.setActionHandler("nexttrack", () => player.next());
|
||||
navigator.mediaSession.setActionHandler("stop", () => {
|
||||
audioCtx.paused = true;
|
||||
audioCtx.currentTime = 0;
|
||||
});
|
||||
}
|
||||
// ...
|
||||
});
|
||||
|
||||
// Persist state changes
|
||||
$effect(() => {
|
||||
// Create a dependency on all persisted fields
|
||||
const state = {
|
||||
queue: player.queue,
|
||||
currentId: player.currentId,
|
||||
volume: player.volume,
|
||||
isMuted: player.isMuted,
|
||||
minimized: !player.uiOpen,
|
||||
};
|
||||
saveState(state);
|
||||
});
|
||||
// ... existing effect for persistence ...
|
||||
|
||||
// Update MediaSession metadata
|
||||
$effect(() => {
|
||||
const track = player.currentTrack;
|
||||
if (track && "mediaSession" in navigator) {
|
||||
navigator.mediaSession.metadata = new MediaMetadata({
|
||||
title: track.title,
|
||||
artist: track.artist,
|
||||
album: track.album || track.animeName,
|
||||
artwork: [
|
||||
// We could add artwork here if available in track
|
||||
// { src: track.artworkUrl, sizes: '512x512', type: 'image/png' }
|
||||
],
|
||||
});
|
||||
}
|
||||
});
|
||||
// ...
|
||||
|
||||
// ... existing effect for playback ...
|
||||
$effect(() => {
|
||||
const track = player.currentTrack;
|
||||
console.log("Playback effect triggered", {
|
||||
trackId: track?.id,
|
||||
src: track?.src,
|
||||
});
|
||||
if (audioEl) {
|
||||
if (track) {
|
||||
const newSrc = track.src;
|
||||
@@ -83,7 +49,14 @@
|
||||
// audioEl.src sets the attribute, currentSrc is the resolved URL
|
||||
const newSrcAbsolute = new URL(newSrc, document.baseURI).href;
|
||||
|
||||
console.log("Src check", {
|
||||
currentSrc,
|
||||
newSrcAbsolute,
|
||||
match: currentSrc === newSrcAbsolute,
|
||||
});
|
||||
|
||||
if (currentSrc !== newSrcAbsolute) {
|
||||
console.log("Setting new src", newSrc);
|
||||
audioEl.src = newSrc;
|
||||
audioEl.play().catch((e) => {
|
||||
console.warn("Autoplay blocked or failed", e);
|
||||
@@ -105,37 +78,25 @@
|
||||
// ... existing callbacks ...
|
||||
|
||||
// Bindings and Event Listeners
|
||||
function onTimeUpdate() {
|
||||
audioCtx.currentTime = audioEl.currentTime;
|
||||
}
|
||||
|
||||
function onDurationChange() {
|
||||
audioCtx.duration = audioEl.duration;
|
||||
}
|
||||
|
||||
function onPlay() {
|
||||
audioCtx.paused = false;
|
||||
if ("mediaSession" in navigator)
|
||||
navigator.mediaSession.playbackState = "playing";
|
||||
}
|
||||
|
||||
function onPause() {
|
||||
audioCtx.paused = true;
|
||||
if ("mediaSession" in navigator)
|
||||
navigator.mediaSession.playbackState = "paused";
|
||||
}
|
||||
|
||||
function onEnded() {
|
||||
player.next();
|
||||
}
|
||||
|
||||
// Sync MediaSession playback state with bound paused state
|
||||
$effect(() => {
|
||||
if ("mediaSession" in navigator) {
|
||||
navigator.mediaSession.playbackState = audioCtx.paused
|
||||
? "paused"
|
||||
: "playing";
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<audio
|
||||
bind:this={audioEl}
|
||||
ontimeupdate={onTimeUpdate}
|
||||
ondurationchange={onDurationChange}
|
||||
onplay={onPlay}
|
||||
onpause={onPause}
|
||||
bind:currentTime={audioCtx.currentTime}
|
||||
bind:duration={audioCtx.duration}
|
||||
bind:paused={audioCtx.paused}
|
||||
onended={onEnded}
|
||||
class="hidden"
|
||||
></audio>
|
||||
|
||||
@@ -13,23 +13,25 @@ export class AudioContext {
|
||||
this.audioEl = el;
|
||||
}
|
||||
|
||||
// Bindings will handle state updates, but we need methods to control play/pause
|
||||
// from other components.
|
||||
// Since we bind to `this.paused`, toggling it here will trigger the audio element.
|
||||
|
||||
play() {
|
||||
this.audioEl?.play();
|
||||
this.paused = false;
|
||||
}
|
||||
|
||||
pause() {
|
||||
this.audioEl?.pause();
|
||||
this.paused = true;
|
||||
}
|
||||
|
||||
toggle() {
|
||||
if (this.paused) this.play();
|
||||
else this.pause();
|
||||
this.paused = !this.paused;
|
||||
}
|
||||
|
||||
seek(time: number) {
|
||||
if (this.audioEl) {
|
||||
this.audioEl.currentTime = Math.max(0, Math.min(time, this.duration));
|
||||
}
|
||||
// Seeking is done by updating currentTime, which is bound to the audio element.
|
||||
this.currentTime = Math.max(0, Math.min(time, this.duration));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user