diff --git a/src/components/player/KSPlayerCore.tsx b/src/components/player/KSPlayerCore.tsx index 4cbef4b..7107e89 100644 --- a/src/components/player/KSPlayerCore.tsx +++ b/src/components/player/KSPlayerCore.tsx @@ -643,6 +643,46 @@ const KSPlayerCore: React.FC = () => { controls.seekToTime(value); }; + // Progress update throttling: + // - Always keep a ref updated (cheap, no re-render) + // - Only push to React state at a lower frequency (prevents full-tree re-render storms) + const currentTimeRef = useRef(currentTime); + const bufferedRef = useRef(buffered); + const lastUiProgressUpdateAtRef = useRef(0); + useEffect(() => { + currentTimeRef.current = currentTime; + }, [currentTime]); + useEffect(() => { + bufferedRef.current = buffered; + }, [buffered]); + + const handleProgress = useCallback((d: any) => { + const t = d?.currentTime ?? 0; + const newBuffered = d?.buffered ?? 0; + + currentTimeRef.current = t; + lastPlaybackTimeRef.current = t || 0; + + // Keep buffered updates coarse to avoid churn + if (Math.abs(newBuffered - bufferedRef.current) > 1) { + bufferedRef.current = newBuffered; + setBuffered(newBuffered); + } + + // Don't fight the slider while the user is dragging it + if (isSliderDragging) return; + + const now = Date.now(); + const needsTightUi = + showControls || paused || customSubs.useCustomSubtitles; + const minIntervalMs = needsTightUi ? 250 : 1000; + + if (now - lastUiProgressUpdateAtRef.current < minIntervalMs) return; + lastUiProgressUpdateAtRef.current = now; + + setCurrentTime(t); + }, [isSliderDragging, paused, showControls, customSubs.useCustomSubtitles, setBuffered, setCurrentTime]); + return (