diff --git a/web/src/components/player/PreviewThumbnailPlayer.tsx b/web/src/components/player/PreviewThumbnailPlayer.tsx index 5a8dacedd..2e3a9cd96 100644 --- a/web/src/components/player/PreviewThumbnailPlayer.tsx +++ b/web/src/components/player/PreviewThumbnailPlayer.tsx @@ -23,6 +23,7 @@ import { useSwipeable } from "react-swipeable"; type PreviewPlayerProps = { review: ReviewSegment; allPreviews?: Preview[]; + scrollLock?: boolean; onTimeUpdate?: React.Dispatch>; setReviewed: (reviewId: string) => void; onClick: (reviewId: string, ctrl: boolean) => void; @@ -39,6 +40,7 @@ type Preview = { export default function PreviewThumbnailPlayer({ review, allPreviews, + scrollLock = false, setReviewed, onClick, onTimeUpdate, @@ -116,12 +118,16 @@ export default function PreviewThumbnailPlayer({ return undefined; } - }, [allPreviews]); + }, [allPreviews, review]); const playingBack = useMemo(() => playback, [playback]); const onPlayback = useCallback( (isHovered: boolean) => { + if (isHovered && scrollLock) { + return; + } + if (isHovered) { setHoverTimeout( setTimeout(() => { @@ -144,7 +150,7 @@ export default function PreviewThumbnailPlayer({ // we know that these deps are correct // eslint-disable-next-line react-hooks/exhaustive-deps - [hoverTimeout, review], + [hoverTimeout, scrollLock, review], ); // date @@ -462,7 +468,7 @@ function VideoPreview({ ) { + const [scrollLock, setScrollLockout] = useState(false); + + const onScroll = useCallback(() => { + if (!scrollLock) { + setScrollLockout(true); + } + }, [scrollLock, setScrollLockout]); + const onMouseMove = useCallback(() => { + if (scrollLock) { + setScrollLockout(false); + } + }, [scrollLock, setScrollLockout]); + + useEffect(() => { + if (isMobile) { + return; + } + + if (!ref.current) { + return; + } + + const content = ref.current; + content.addEventListener("scroll", onScroll); + content.addEventListener("mousemove", onMouseMove); + + return () => { + content.removeEventListener("scroll", onScroll); + content.removeEventListener("mousemove", onMouseMove); + }; + }, [ref, onScroll, onMouseMove]); + + return scrollLock; +} diff --git a/web/src/views/events/EventView.tsx b/web/src/views/events/EventView.tsx index 9889a6d6c..0bae5eefa 100644 --- a/web/src/views/events/EventView.tsx +++ b/web/src/views/events/EventView.tsx @@ -7,6 +7,7 @@ import EventReviewTimeline from "@/components/timeline/EventReviewTimeline"; import ActivityIndicator from "@/components/ui/activity-indicator"; import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"; import { useEventUtils } from "@/hooks/use-event-utils"; +import { useScrollLockout } from "@/hooks/use-mouse-listener"; import { FrigateConfig } from "@/types/frigateConfig"; import { Preview } from "@/types/preview"; import { ReviewFilter, ReviewSegment, ReviewSeverity } from "@/types/review"; @@ -192,6 +193,7 @@ export default function EventView({ // preview playback const [previewTime, setPreviewTime] = useState(); + const scrollLock = useScrollLockout(contentRef); // review interaction @@ -220,7 +222,7 @@ export default function EventView({ onOpenReview(reviewId); } }, - [selectedReviews, setSelectedReviews], + [selectedReviews, setSelectedReviews, onOpenReview], ); const exportReview = useCallback( @@ -236,7 +238,7 @@ export default function EventView({ { playback: "realtime" }, ); }, - [selectedReviews], + [currentItems], ); if (!config) { @@ -342,6 +344,7 @@ export default function EventView({ review={value} allPreviews={relevantPreviews} setReviewed={markItemAsReviewed} + scrollLock={scrollLock} onTimeUpdate={setPreviewTime} onClick={onSelectReview} />