fix: 修复小窗闭包过期、详情页 loading 卡死、视频播放器性能问题

- 小窗 PanResponder 用 storeRef 替代闭包捕获,修复 roomId/bvid 始终为初始值
- useLiveDetail 用 ref 比对替代 cancelled 标志,防止 fetch 被意外取消
- 详情页 useLayoutEffect 同步清除小窗,BigVideoCard 小窗活跃时跳过播放
- 视频播放器竖屏/全屏互斥渲染,减半解码器占用
- onProgress 节流 + 退出全屏强制恢复播放
This commit is contained in:
Developer
2026-03-25 15:03:49 +08:00
parent 68b8b7d665
commit e3def7d01b
11 changed files with 147 additions and 118 deletions

View File

@@ -32,9 +32,6 @@ export function VideoPlayer({ playData, qualities, currentQn, onQualityChange, b
};
const handleExitFullscreen = async () => {
// 退出全屏:同步进度,竖屏一律暂停
portraitRef.current?.seek(lastTimeRef.current);
portraitRef.current?.setPaused(true);
setFullscreen(false);
if (Platform.OS !== 'web')
await ScreenOrientation?.lockAsync(ScreenOrientation.OrientationLock.PORTRAIT_UP);
@@ -71,46 +68,49 @@ export function VideoPlayer({ playData, qualities, currentQn, onQualityChange, b
return (
<>
{/* Portrait player: always mounted, force-paused while fullscreen is active */}
<NativeVideoPlayer
ref={portraitRef}
playData={playData}
qualities={qualities}
currentQn={currentQn}
onQualityChange={onQualityChange}
onFullscreen={handleEnterFullscreen}
bvid={bvid}
cid={cid}
isFullscreen={false}
forcePaused={fullscreen}
initialTime={lastTimeRef.current}
onTimeUpdate={(t) => { lastTimeRef.current = t; onTimeUpdate?.(t); }}
/>
{/* 竖屏和全屏互斥渲染,避免同时挂载两个视频解码器 */}
{!fullscreen && (
<NativeVideoPlayer
ref={portraitRef}
playData={playData}
qualities={qualities}
currentQn={currentQn}
onQualityChange={onQualityChange}
onFullscreen={handleEnterFullscreen}
bvid={bvid}
cid={cid}
isFullscreen={false}
initialTime={lastTimeRef.current}
onTimeUpdate={(t) => { lastTimeRef.current = t; onTimeUpdate?.(t); }}
/>
)}
<Modal visible={fullscreen} animationType="none" statusBarTranslucent>
<StatusBar hidden />
<View style={{ flex: 1, backgroundColor: '#000', justifyContent: 'center', alignItems: 'center' }}>
<View style={needsRotation
? { width: height, height: width, transform: [{ rotate: '90deg' }] }
: { flex: 1, width: '100%' }
}>
<NativeVideoPlayer
playData={playData}
qualities={qualities}
currentQn={currentQn}
onQualityChange={onQualityChange}
onFullscreen={handleExitFullscreen}
bvid={bvid}
cid={cid}
danmakus={danmakus}
isFullscreen={true}
initialTime={lastTimeRef.current}
onTimeUpdate={(t) => { lastTimeRef.current = t; onTimeUpdate?.(t); }}
style={needsRotation ? { width: height, height: width } : { flex: 1 }}
/>
{fullscreen && (
<Modal visible animationType="none" statusBarTranslucent>
<StatusBar hidden />
<View style={{ flex: 1, backgroundColor: '#000', justifyContent: 'center', alignItems: 'center' }}>
<View style={needsRotation
? { width: height, height: width, transform: [{ rotate: '90deg' }] }
: { flex: 1, width: '100%' }
}>
<NativeVideoPlayer
playData={playData}
qualities={qualities}
currentQn={currentQn}
onQualityChange={onQualityChange}
onFullscreen={handleExitFullscreen}
bvid={bvid}
cid={cid}
danmakus={danmakus}
isFullscreen={true}
initialTime={lastTimeRef.current}
onTimeUpdate={(t) => { lastTimeRef.current = t; onTimeUpdate?.(t); }}
style={needsRotation ? { width: height, height: width } : { flex: 1 }}
/>
</View>
</View>
</View>
</Modal>
</Modal>
)}
</>
);
}