From 2f897d7f62f79a394e9ff26ac55a440f100dbc4a Mon Sep 17 00:00:00 2001 From: shinya Date: Thu, 7 Aug 2025 21:51:20 +0800 Subject: [PATCH] feat: request wake lock when play --- VERSION.txt | 2 +- src/app/play/page.tsx | 110 ++++++++++++++++++++++++++++++++++++++---- src/lib/version.ts | 2 +- 3 files changed, 103 insertions(+), 11 deletions(-) diff --git a/VERSION.txt b/VERSION.txt index 6ae9c9b..fd540e9 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -20250807010230 \ No newline at end of file +20250807215120 \ No newline at end of file diff --git a/src/app/play/page.tsx b/src/app/play/page.tsx index 9b2e9bb..5bc41da 100644 --- a/src/app/play/page.tsx +++ b/src/app/play/page.tsx @@ -34,6 +34,14 @@ declare global { } } +// Wake Lock API 类型声明 +interface WakeLockSentinel { + released: boolean; + release(): Promise; + addEventListener(type: 'release', listener: () => void): void; + removeEventListener(type: 'release', listener: () => void): void; +} + function PlayPageClient() { const router = useRouter(); const searchParams = useSearchParams(); @@ -195,6 +203,9 @@ function PlayPageClient() { const artPlayerRef = useRef(null); const artRef = useRef(null); + // Wake Lock 相关 + const wakeLockRef = useRef(null); + // ----------------------------------------------------------------------------- // 工具函数(Utils) // ----------------------------------------------------------------------------- @@ -437,6 +448,53 @@ function PlayPageClient() { } }; + // Wake Lock 相关函数 + const requestWakeLock = async () => { + try { + if ('wakeLock' in navigator) { + wakeLockRef.current = await (navigator as any).wakeLock.request( + 'screen' + ); + console.log('Wake Lock 已启用'); + } + } catch (err) { + console.warn('Wake Lock 请求失败:', err); + } + }; + + const releaseWakeLock = async () => { + try { + if (wakeLockRef.current) { + await wakeLockRef.current.release(); + wakeLockRef.current = null; + console.log('Wake Lock 已释放'); + } + } catch (err) { + console.warn('Wake Lock 释放失败:', err); + } + }; + + // 清理播放器资源的统一函数 + const cleanupPlayer = () => { + if (artPlayerRef.current) { + try { + // 销毁 HLS 实例 + if (artPlayerRef.current.video && artPlayerRef.current.video.hls) { + artPlayerRef.current.video.hls.destroy(); + } + + // 销毁 ArtPlayer 实例 + artPlayerRef.current.destroy(); + artPlayerRef.current = null; + + console.log('播放器资源已清理'); + } catch (err) { + console.warn('清理播放器资源时出错:', err); + artPlayerRef.current = null; + } + } + }; + // 去广告相关函数 function filterAdsFromM3U8(m3u8Content: string): string { if (!m3u8Content) return ''; @@ -1066,15 +1124,23 @@ function PlayPageClient() { }; useEffect(() => { - // 页面即将卸载时保存播放进度 + // 页面即将卸载时保存播放进度和清理资源 const handleBeforeUnload = () => { saveCurrentPlayProgress(); + releaseWakeLock(); + cleanupPlayer(); }; - // 页面可见性变化时保存播放进度 + // 页面可见性变化时保存播放进度和释放 Wake Lock const handleVisibilityChange = () => { if (document.visibilityState === 'hidden') { saveCurrentPlayProgress(); + releaseWakeLock(); + } else if (document.visibilityState === 'visible') { + // 页面重新可见时,如果正在播放则重新请求 Wake Lock + if (artPlayerRef.current && !artPlayerRef.current.paused) { + requestWakeLock(); + } } }; @@ -1215,12 +1281,7 @@ function PlayPageClient() { // WebKit浏览器或首次创建:销毁之前的播放器实例并创建新的 if (artPlayerRef.current) { - if (artPlayerRef.current.video && artPlayerRef.current.video.hls) { - artPlayerRef.current.video.hls.destroy(); - } - // 销毁播放器实例 - artPlayerRef.current.destroy(); - artPlayerRef.current = null; + cleanupPlayer(); } try { @@ -1433,8 +1494,32 @@ function PlayPageClient() { // 监听播放器事件 artPlayerRef.current.on('ready', () => { setError(null); + + // 播放器就绪后,如果正在播放则请求 Wake Lock + if (artPlayerRef.current && !artPlayerRef.current.paused) { + requestWakeLock(); + } }); + // 监听播放状态变化,控制 Wake Lock + artPlayerRef.current.on('play', () => { + requestWakeLock(); + }); + + artPlayerRef.current.on('pause', () => { + releaseWakeLock(); + saveCurrentPlayProgress(); + }); + + artPlayerRef.current.on('video:ended', () => { + releaseWakeLock(); + }); + + // 如果播放器初始化时已经在播放状态,则请求 Wake Lock + if (artPlayerRef.current && !artPlayerRef.current.paused) { + requestWakeLock(); + } + artPlayerRef.current.on('video:volumechange', () => { lastVolumeRef.current = artPlayerRef.current.volume; }); @@ -1574,12 +1659,19 @@ function PlayPageClient() { } }, [Artplayer, Hls, videoUrl, loading, blockAdEnabled]); - // 当组件卸载时清理定时器 + // 当组件卸载时清理定时器、Wake Lock 和播放器资源 useEffect(() => { return () => { + // 清理定时器 if (saveIntervalRef.current) { clearInterval(saveIntervalRef.current); } + + // 释放 Wake Lock + releaseWakeLock(); + + // 销毁播放器实例 + cleanupPlayer(); }; }, []); diff --git a/src/lib/version.ts b/src/lib/version.ts index 169c17a..9f95a8c 100644 --- a/src/lib/version.ts +++ b/src/lib/version.ts @@ -2,7 +2,7 @@ 'use client'; -const CURRENT_VERSION = '20250807010230'; +const CURRENT_VERSION = '20250807215120'; // 版本检查结果枚举 export enum UpdateStatus {