feat: Add Media Session API support for browser media controls
- Implement `updateMediaSession()` to sync track metadata (title, artist, artwork) with browser's media session - Update playback state (`playing`/`paused`) via `mediaSession.playbackState` - Register action handlers for common media controls: play, pause, next/prev track, seek operations - Integrate `updateMediaSession()` call into `playCurrent()` to show metadata when playback starts Enables native browser media notification and lock screen controls on supported platforms.
This commit is contained in:
parent
3586e1da9a
commit
5eadf57068
|
|
@ -62,6 +62,19 @@
|
|||
});
|
||||
}
|
||||
|
||||
function updateMediaSession() {
|
||||
if (!('mediaSession' in navigator)) return;
|
||||
const cur = state.queue[state.index];
|
||||
if (!cur) return;
|
||||
navigator.mediaSession.metadata = new MediaMetadata({
|
||||
title: cur.title,
|
||||
artist: cur.artist || '',
|
||||
artwork: cur.cover
|
||||
? [{ src: new URL(cur.cover, window.location.origin).href, sizes: '512x512', type: 'image/jpeg' }]
|
||||
: [],
|
||||
});
|
||||
}
|
||||
|
||||
function playCurrent() {
|
||||
const cur = state.queue[state.index];
|
||||
if (!cur) return;
|
||||
|
|
@ -72,6 +85,7 @@
|
|||
.catch((err) => console.warn('play failed', err));
|
||||
render();
|
||||
highlightNowPlaying(cur.id);
|
||||
updateMediaSession();
|
||||
}
|
||||
|
||||
function playOne(song) {
|
||||
|
|
@ -98,9 +112,25 @@
|
|||
}
|
||||
}
|
||||
|
||||
function prev() {
|
||||
if (state.index > 0) { state.index -= 1; playCurrent(); }
|
||||
}
|
||||
|
||||
audio.addEventListener('ended', next);
|
||||
audio.addEventListener('play', () => { if ('mediaSession' in navigator) navigator.mediaSession.playbackState = 'playing'; });
|
||||
audio.addEventListener('pause', () => { if ('mediaSession' in navigator) navigator.mediaSession.playbackState = 'paused'; });
|
||||
nextBtn.addEventListener('click', next);
|
||||
|
||||
if ('mediaSession' in navigator) {
|
||||
navigator.mediaSession.setActionHandler('play', () => audio.play());
|
||||
navigator.mediaSession.setActionHandler('pause', () => audio.pause());
|
||||
navigator.mediaSession.setActionHandler('nexttrack', () => next());
|
||||
navigator.mediaSession.setActionHandler('previoustrack', () => prev());
|
||||
navigator.mediaSession.setActionHandler('seekto', (d) => { audio.currentTime = d.seekTime; });
|
||||
navigator.mediaSession.setActionHandler('seekbackward', (d) => { audio.currentTime = Math.max(0, audio.currentTime - (d.seekOffset || 10)); });
|
||||
navigator.mediaSession.setActionHandler('seekforward', (d) => { audio.currentTime = Math.min(audio.duration || Infinity, audio.currentTime + (d.seekOffset || 10)); });
|
||||
}
|
||||
|
||||
repeatBtn.addEventListener('click', () => {
|
||||
repeatOn = !repeatOn;
|
||||
repeatBtn.classList.toggle('active', repeatOn);
|
||||
|
|
|
|||
Loading…
Reference in New Issue