mirror of
				https://github.com/blakeblackshear/frigate.git
				synced 2025-10-27 10:52:11 +01:00 
			
		
		
		
	Implement scroll lock for previews (#10180)
* Implement scroll lock * Fix seekbar not working
This commit is contained in:
		
							parent
							
								
									ebf34ce378
								
							
						
					
					
						commit
						a67e970fca
					
				| @ -23,6 +23,7 @@ import { useSwipeable } from "react-swipeable"; | ||||
| type PreviewPlayerProps = { | ||||
|   review: ReviewSegment; | ||||
|   allPreviews?: Preview[]; | ||||
|   scrollLock?: boolean; | ||||
|   onTimeUpdate?: React.Dispatch<React.SetStateAction<number | undefined>>; | ||||
|   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({ | ||||
|         <source src={relevantPreview.src} type={relevantPreview.type} /> | ||||
|       </video> | ||||
|       <Slider | ||||
|         className="absolute inset-x-0 bottom-0" | ||||
|         className="absolute inset-x-0 bottom-0 z-30" | ||||
|         value={[progress]} | ||||
|         onValueChange={onManualSeek} | ||||
|         onValueCommit={onStopManualSeek} | ||||
| @ -580,7 +586,7 @@ function InProgressPreview({ | ||||
|         onLoad={handleLoad} | ||||
|       /> | ||||
|       <Slider | ||||
|         className="absolute inset-x-0 bottom-0" | ||||
|         className="absolute inset-x-0 bottom-0 z-30" | ||||
|         value={[key]} | ||||
|         onValueChange={onManualSeek} | ||||
|         onValueCommit={onStopManualSeek} | ||||
|  | ||||
							
								
								
									
										38
									
								
								web/src/hooks/use-mouse-listener.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								web/src/hooks/use-mouse-listener.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,38 @@ | ||||
| import { MutableRefObject, useCallback, useEffect, useState } from "react"; | ||||
| import { isMobile } from "react-device-detect"; | ||||
| 
 | ||||
| export function useScrollLockout(ref: MutableRefObject<HTMLElement | null>) { | ||||
|   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; | ||||
| } | ||||
| @ -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<number>(); | ||||
|   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} | ||||
|                       /> | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user