From 92093ef80d8482272b3aa150518920cb97bb18b8 Mon Sep 17 00:00:00 2001 From: Astrian Zheng Date: Wed, 4 Jun 2025 20:54:54 +1000 Subject: [PATCH] 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) {