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

@@ -109,8 +109,10 @@ export const NativeVideoPlayer = forwardRef<NativeVideoPlayerRef, Props>(
const [paused, setPaused] = useState(false);
const [currentTime, setCurrentTime] = useState(0);
const currentTimeRef = useRef(0);
const [duration, setDuration] = useState(0);
const durationRef = useRef(0);
const lastProgressUpdate = useRef(0);
const [showQuality, setShowQuality] = useState(false);
@@ -318,16 +320,6 @@ export const NativeVideoPlayer = forwardRef<NativeVideoPlayerRef, Props>(
const local = frameIdx % framesPerSheet;
const col = local % img_x_len;
const row = Math.floor(local / img_x_len);
console.log("[thumb]", {
seekTime,
duration,
indexLen: index?.length,
frameIdx,
totalFrames,
sheetIdx,
col,
row,
});
// 根据单帧图尺寸和预设的显示宽度计算缩放后的显示尺寸,保持宽高比
const scale = THUMB_DISPLAY_W / TW;
const DW = THUMB_DISPLAY_W;
@@ -396,20 +388,32 @@ export const NativeVideoPlayer = forwardRef<NativeVideoPlayerRef, Props>(
resizeMode="contain"
controls={false}
paused={!!(forcePaused || paused)}
progressUpdateInterval={500}
onProgress={({
currentTime: ct,
seekableDuration: dur,
playableDuration: buf,
}) => {
setCurrentTime(ct);
if (dur > 0) setDuration(dur);
setBuffered(buf);
currentTimeRef.current = ct;
onTimeUpdate?.(ct);
// 拖动进度条时跳过 UI 更新,避免与用户拖动冲突
if (isSeekingRef.current) return;
const now = Date.now();
if (now - lastProgressUpdate.current < 450) return;
lastProgressUpdate.current = now;
setCurrentTime(ct);
if (dur > 0 && Math.abs(dur - durationRef.current) > 1) setDuration(dur);
setBuffered(buf);
}}
onLoad={() => {
if (initialTime && initialTime > 0) {
videoRef.current?.seek(initialTime);
}
// seek 后部分播放器不恢复播放,先暂停再恢复,强制触发 prop 变化
if (!forcePaused) {
setPaused(true);
requestAnimationFrame(() => setPaused(false));
}
}}
onError={(e) => {
// 杜比视界播放失败时自动降级到 1080P