mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-09-24 18:26:51 +03:00
fix latched loading spinner after cancelling a timeline selection (#24162)
isLoading and isBuffering only clear on playback progress, and scrubbing holds the player paused, so a source rebuild during a timeline selection left them set with nothing able to clear them. Cancelling made them visible as a spinner over an already-loaded frame, which stayed until the next manual seek. Leaving a scrub now clears them when the source is loaded and the element holds a frame.
This commit is contained in:
committed by
Nicolas Mowen
parent
d183f03fee
commit
9eef369dd0
@@ -158,6 +158,7 @@ export default function DynamicVideoPlayer({
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [isBuffering, setIsBuffering] = useState(false);
|
||||
const loadingTimeoutRef = useRef<NodeJS.Timeout | undefined>(undefined);
|
||||
const prevCameraRef = useRef(camera);
|
||||
|
||||
// Don't set source until recordings load - we need accurate startPosition
|
||||
// to avoid hls.js clamping to video end when startPosition exceeds duration
|
||||
@@ -166,13 +167,34 @@ export default function DynamicVideoPlayer({
|
||||
// start at correct time
|
||||
|
||||
useEffect(() => {
|
||||
// isLoading/isBuffering only clear on playback progress, which a
|
||||
// paused scrub never reaches. A camera switch is excluded: its old
|
||||
// source still reads as settled while the new one is fetched
|
||||
const scrubExit = prevCameraRef.current === camera;
|
||||
prevCameraRef.current = camera;
|
||||
const settled = () =>
|
||||
sourceLoadedRef.current &&
|
||||
(playerRef.current?.readyState ?? 0) >=
|
||||
HTMLMediaElement.HAVE_CURRENT_DATA;
|
||||
|
||||
if (!isScrubbing && scrubExit && settled()) {
|
||||
setIsLoading(false);
|
||||
setIsBuffering(false);
|
||||
}
|
||||
|
||||
if (!isScrubbing) {
|
||||
// never overwrite a pending timer: an orphaned one escapes
|
||||
// onPlaying's clearTimeout and flashes loading mid-playback
|
||||
if (loadingTimeoutRef.current) {
|
||||
clearTimeout(loadingTimeoutRef.current);
|
||||
}
|
||||
loadingTimeoutRef.current = setTimeout(() => setIsLoading(true), 1000);
|
||||
loadingTimeoutRef.current = setTimeout(() => {
|
||||
// re-checked here: readyState drops while a seek loads
|
||||
if (scrubExit && settled()) {
|
||||
return;
|
||||
}
|
||||
setIsLoading(true);
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
return () => {
|
||||
|
||||
Reference in New Issue
Block a user