feat(Player): 添加媒体会话元数据和播放控制功能

为播放器组件添加了媒体会话元数据设置功能,包括歌曲标题、艺术家、专辑和封面信息。同时实现了上一曲和下一曲的播放控制逻辑,并优化了音频元素的交互事件处理。
This commit is contained in:
Astrian Zheng 2025-05-24 23:40:13 +10:00
parent 6743b694c8
commit 2ffa445413
Signed by: Astrian
SSH Key Fingerprint: SHA256:rVnhx3DAKjujCwWE13aDl7uV6+9U1MvydLkNRXJrBiA

View File

@ -7,17 +7,69 @@ const playQueueStore = usePlayQueueStore()
const player = useTemplateRef('playerRef') const player = useTemplateRef('playerRef')
watch(() => playQueueStore.isPlaying, (newValue) => { watch(() => playQueueStore.isPlaying, (newValue) => {
if (newValue) { player.value?.play() } if (newValue) {
player.value?.play()
setMetadata()
}
else { player.value?.pause() } else { player.value?.pause() }
}) })
watch(() => playQueueStore.currentIndex, () => {
setMetadata()
})
function artistsOrganize(list: string[]) {
if (list.length === 0) { return '未知音乐人' }
return list.map((artist) => {
return artist
}).join(' / ')
}
function setMetadata() {
if ('mediaSession' in navigator) {
navigator.mediaSession.metadata = new MediaMetadata({
title: playQueueStore.list[playQueueStore.currentIndex].song.name,
artist: artistsOrganize(playQueueStore.list[playQueueStore.currentIndex].song.artists ?? []),
album: playQueueStore.list[playQueueStore.currentIndex].album?.name,
artwork: [
{ src: playQueueStore.list[playQueueStore.currentIndex].album?.coverUrl ?? '', sizes: '500x500', type: 'image/png' },
]
})
navigator.mediaSession.setActionHandler('previoustrack', playPrevious)
navigator.mediaSession.setActionHandler('nexttrack', playNext)
}
}
function playNext() {
if (playQueueStore.currentIndex === playQueueStore.list.length - 1) {
playQueueStore.currentIndex = 0
player.value?.pause()
} else {
playQueueStore.currentIndex++
player.value?.play()
}
}
function playPrevious() {
if (player.value && (player.value.currentTime ?? 0) < 5 && playQueueStore.currentIndex > 0) {
playQueueStore.currentIndex--
player.value?.play()
} else {
if (player.value) { player.value.currentTime = 0 }
}
}
</script> </script>
<template> <template>
<div> <div>
<audio :src="playQueueStore.list[playQueueStore.currentIndex] ? playQueueStore.list[playQueueStore.currentIndex].song.sourceUrl : ''" ref="playerRef" autoplay v-if="playQueueStore.list.length !== 0"></audio> <audio
:src="playQueueStore.list[playQueueStore.currentIndex] ? playQueueStore.list[playQueueStore.currentIndex].song.sourceUrl : ''"
ref="playerRef" autoplay v-if="playQueueStore.list.length !== 0" @ended="playNext" @pause="playQueueStore.isPlaying = false" @play="playQueueStore.isPlaying = true">
</audio>
<div <div
class="text-white w-48 h-9 bg-neutral-800/80 border border-[#ffffff39] rounded-full text-center backdrop-blur-3xl flex gap-2 overflow-hidden" class="text-white w-48 h-9 bg-neutral-800/80 border border-[#ffffff39] rounded-full text-center backdrop-blur-3xl flex gap-2 overflow-hidden select-none"
v-if="playQueueStore.list.length !== 0"> v-if="playQueueStore.list.length !== 0">
<img :src="playQueueStore.list[playQueueStore.currentIndex].album?.coverUrl ?? ''" class="rounded-full" /> <img :src="playQueueStore.list[playQueueStore.currentIndex].album?.coverUrl ?? ''" class="rounded-full" />
<div class="flex-1 flex items-center"> <div class="flex-1 flex items-center">