From 92093ef80d8482272b3aa150518920cb97bb18b8 Mon Sep 17 00:00:00 2001 From: Astrian Zheng Date: Wed, 4 Jun 2025 20:54:54 +1000 Subject: [PATCH 01/10] fix: resolve playroom UI state inconsistency when page loses focus MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When lyrics are enabled and the page loses focus while playing a song without lyrics, then plays a song with lyrics, returning to the page caused controller and lyrics layout to become misaligned. Added page focus handlers to sync UI state correctly. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- src/components/ScrollingLyrics.vue | 36 ++++++++++++ src/pages/Playroom.vue | 92 ++++++++++++++++++++++++++++++ 2 files changed, 128 insertions(+) diff --git a/src/components/ScrollingLyrics.vue b/src/components/ScrollingLyrics.vue index 60bddc1..05f762e 100644 --- a/src/components/ScrollingLyrics.vue +++ b/src/components/ScrollingLyrics.vue @@ -543,8 +543,39 @@ watch(() => props.lrcSrc, async (newSrc) => { } }, { immediate: true }) + +// 页面焦点处理函数变量声明 +let handleVisibilityChange: (() => void) | null = null + +// 页面焦点处理 +function setupPageFocusHandlers() { + handleVisibilityChange = () => { + if (document.hidden) { + // 页面失去焦点时暂停动画 + if (scrollTween) scrollTween.pause() + if (highlightTween) highlightTween.pause() + } else { + // 页面重新获得焦点时恢复并重新同步 + if (scrollTween && scrollTween.paused()) scrollTween.resume() + if (highlightTween && highlightTween.paused()) highlightTween.resume() + + // 重新同步歌词位置 + nextTick(() => { + if (currentLineIndex.value >= 0 && autoScroll.value && !userScrolling.value) { + scrollToLine(currentLineIndex.value, false) // 不使用动画,直接定位 + } + }) + } + } + + document.addEventListener('visibilitychange', handleVisibilityChange) +} + // 组件挂载时的入场动画 onMounted(() => { + // 设置页面焦点处理 + setupPageFocusHandlers() + // 控制面板入场动画 if (controlPanel.value) { gsap.fromTo(controlPanel.value, @@ -577,6 +608,11 @@ onUnmounted(() => { if (scrollTween) scrollTween.kill() if (highlightTween) highlightTween.kill() if (userScrollTimeout) clearTimeout(userScrollTimeout) + + // 清理页面焦点事件监听器 + if (handleVisibilityChange) { + document.removeEventListener('visibilitychange', handleVisibilityChange) + } }) // 暴露方法给父组件 diff --git a/src/pages/Playroom.vue b/src/pages/Playroom.vue index 652aa57..1f38610 100644 --- a/src/pages/Playroom.vue +++ b/src/pages/Playroom.vue @@ -83,6 +83,9 @@ onMounted(async () => { thumbUpdate() setupEntranceAnimations() + + // 添加页面焦点事件监听 + setupPageFocusHandlers() }) function timeFormatter(time: number) { @@ -419,9 +422,98 @@ watch(() => [preferences.presentLyrics, getCurrentTrack()?.song.lyricUrl], (newV } }, { immediate: true }) +// 页面焦点处理函数变量声明 +let handleVisibilityChange: (() => void) | null = null +let handlePageFocus: (() => void) | null = null + onUnmounted(() => { + // 清理页面焦点事件监听器 + if (handleVisibilityChange) { + document.removeEventListener('visibilitychange', handleVisibilityChange) + } + if (handlePageFocus) { + window.removeEventListener('focus', handlePageFocus) + } }) +// 页面焦点处理函数 +function setupPageFocusHandlers() { + handleVisibilityChange = () => { + if (document.hidden) { + // 页面失去焦点时,暂停所有动画 + console.log('[Playroom] 页面失去焦点,暂停动画') + } else { + // 页面重新获得焦点时,重新同步状态 + console.log('[Playroom] 页面重新获得焦点,同步状态') + nextTick(() => { + resyncLyricsState() + }) + } + } + + handlePageFocus = () => { + console.log('[Playroom] 窗口获得焦点,同步状态') + nextTick(() => { + resyncLyricsState() + }) + } + + // 监听页面可见性变化 + document.addEventListener('visibilitychange', handleVisibilityChange) + window.addEventListener('focus', handlePageFocus) +} + +// 重新同步歌词状态 +function resyncLyricsState() { + const currentTrack = getCurrentTrack() + if (!currentTrack) return + + console.log('[Playroom] 重新同步歌词状态') + + // 重置动画状态 + if (controllerRef.value) { + gsap.set(controllerRef.value, { + marginLeft: '0rem', + marginRight: '0rem' + }) + } + + if (lyricsSection.value) { + gsap.set(lyricsSection.value, { + opacity: 1, + x: 0, + y: 0, + scale: 1 + }) + } + + // 检查当前歌词显示状态应该是什么 + const shouldShowLyrics = preferences.presentLyrics && currentTrack.song.lyricUrl ? true : false + + if (shouldShowLyrics !== presentLyrics.value) { + console.log(`[Playroom] 歌词状态不一致,重新设置: ${presentLyrics.value} -> ${shouldShowLyrics}`) + + // 直接设置状态,不触发动画 + presentLyrics.value = shouldShowLyrics + + // 如果需要显示歌词,重新执行显示动画 + if (shouldShowLyrics) { + nextTick(() => { + const tl = gsap.timeline() + tl.from(controllerRef.value, { + marginRight: '-40rem', + duration: 0.4, + ease: "power2.out" + }).fromTo(lyricsSection.value, + { opacity: 0, x: 50, scale: 0.95 }, + { opacity: 1, x: 0, scale: 1, duration: 0.5, ease: "power2.out" }, + "-=0.2" + ) + }) + } + } +} + // New: Watch for track changes and animate watch(() => playQueueStore.currentIndex, () => { if (albumCover.value) { From 672b2d80d51a3a53a6d0f7c2104a28af8035ecfa Mon Sep 17 00:00:00 2001 From: Astrian Zheng Date: Wed, 4 Jun 2025 21:02:24 +1000 Subject: [PATCH 02/10] refactor: simplify currentTrack computed property in Player.vue MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove unnecessary else clause for cleaner code structure. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- src/components/Player.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/Player.vue b/src/components/Player.vue index 3e0d03b..4270355 100644 --- a/src/components/Player.vue +++ b/src/components/Player.vue @@ -24,9 +24,9 @@ console.log('[Player] 检查 store 方法:', { const currentTrack = computed(() => { if (playQueueStore.playMode.shuffle && playQueueStore.shuffleList.length > 0) { return playQueueStore.list[playQueueStore.shuffleList[playQueueStore.currentIndex]] - } else { - return playQueueStore.list[playQueueStore.currentIndex] } + + return playQueueStore.list[playQueueStore.currentIndex] }) // 获取当前歌曲的音频源 From 6461c0adac90875dbd6e4221c95400cb7717df9c Mon Sep 17 00:00:00 2001 From: Astrian Zheng Date: Wed, 4 Jun 2025 21:03:09 +1000 Subject: [PATCH 03/10] style: add text-xs class to player title for non-Chrome browsers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ensure consistent font size rendering across different browsers by applying Tailwind's text-xs utility class to the song title in the mini player component. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- src/components/Player.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Player.vue b/src/components/Player.vue index 4270355..0d95150 100644 --- a/src/components/Player.vue +++ b/src/components/Player.vue @@ -395,7 +395,7 @@ setInterval(syncVolumeFromStorage, 100)
- {{ getCurrentTrack()?.song.name }} + {{ getCurrentTrack()?.song.name }}
From 1c5ee950867fc0af64fc926223b73b9a6f8d21b1 Mon Sep 17 00:00:00 2001 From: Astrian Zheng Date: Wed, 4 Jun 2025 21:07:19 +1000 Subject: [PATCH 04/10] refactor: improve code quality in Playroom.vue MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Use Number.isNaN instead of isNaN for better type safety - Convert anonymous function to arrow function for consistency - Add explicit braces to single-line if statement for clarity 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- src/pages/Playroom.vue | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/pages/Playroom.vue b/src/pages/Playroom.vue index 1f38610..82f3a3e 100644 --- a/src/pages/Playroom.vue +++ b/src/pages/Playroom.vue @@ -93,7 +93,7 @@ function timeFormatter(time: number) { if (timeInSeconds < 0) { return '-:--' } const minutes = Math.floor(timeInSeconds / 60) const seconds = Math.floor(timeInSeconds % 60) - if (isNaN(minutes) || isNaN(seconds)) { return '-:--' } + if (Number.isNaN(minutes) || Number.isNaN(seconds)) { return '-:--' } return `${minutes}:${seconds < 10 ? '0' : ''}${seconds}` } @@ -158,7 +158,7 @@ function createVolumeDraggable() { // 保存音量到localStorage localStorage.setItem('audioVolume', newVolume.toString()) }, - onDragEnd: function () { + onDragEnd: () => { // 拖拽结束时也保存一次 localStorage.setItem('audioVolume', volume.value.toString()) } @@ -466,7 +466,7 @@ function setupPageFocusHandlers() { // 重新同步歌词状态 function resyncLyricsState() { const currentTrack = getCurrentTrack() - if (!currentTrack) return + if (!currentTrack) { return } console.log('[Playroom] 重新同步歌词状态') From 612d673cbb898dbcd7ac47763ccbc0fc7ffd2a45 Mon Sep 17 00:00:00 2001 From: Astrian Zheng Date: Wed, 4 Jun 2025 21:07:38 +1000 Subject: [PATCH 05/10] style: add text-xs classes to playroom time displays for consistency MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ensure consistent font sizing across different browsers by applying Tailwind's text-xs utility classes to current time, format detector, and duration display elements in the playroom interface. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- src/pages/Playroom.vue | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/pages/Playroom.vue b/src/pages/Playroom.vue index 82f3a3e..4aa4c43 100644 --- a/src/pages/Playroom.vue +++ b/src/pages/Playroom.vue @@ -605,9 +605,9 @@ watch(() => playQueueStore.currentIndex, () => {
-
+
{{ timeFormatter(Math.floor(playQueueStore.currentTime)) }} + class="text-black blur-lg absolute top-0 text-xs">{{ timeFormatter(Math.floor(playQueueStore.currentTime)) }} {{ timeFormatter(Math.floor(playQueueStore.currentTime)) }}
@@ -618,7 +618,7 @@ watch(() => playQueueStore.currentIndex, () => {