* various tweaks

* update debounce time

* scroll to top with new events
This commit is contained in:
Josh Hawkins 2024-02-23 07:52:54 -06:00 committed by GitHub
parent fc94fcb2ac
commit 7d18c2c03d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 91 additions and 64 deletions

View File

@ -187,14 +187,7 @@ export function EventReviewTimeline({
setCurrentTimeSegment(alignedHandlebarTime); setCurrentTimeSegment(alignedHandlebarTime);
} }
}, [ }, []);
handlebarTime,
segmentDuration,
showHandlebar,
timelineDuration,
timelineStart,
alignDateToTimeline,
]);
useEffect(() => { useEffect(() => {
generateSegments(); generateSegments();

View File

@ -186,14 +186,20 @@ export function EventSegment({
const firstMinimapSegmentRef = useRef<HTMLDivElement>(null); const firstMinimapSegmentRef = useRef<HTMLDivElement>(null);
let debounceTimer: ReturnType<typeof setTimeout>;
function debounceScrollIntoView(element: HTMLElement) {
clearTimeout(debounceTimer);
debounceTimer = setTimeout(() => {
element.scrollIntoView({ behavior: "smooth", block: "center" });
}, 100);
}
useEffect(() => { useEffect(() => {
// Check if the first segment is out of view // Check if the first segment is out of view
const firstSegment = firstMinimapSegmentRef.current; const firstSegment = firstMinimapSegmentRef.current;
if (firstSegment && showMinimap && isFirstSegmentInMinimap) { if (firstSegment && showMinimap && isFirstSegmentInMinimap) {
firstSegment.scrollIntoView({ debounceScrollIntoView(firstSegment);
behavior: "smooth",
block: "center",
});
} }
}, [showMinimap, isFirstSegmentInMinimap, events, segmentDuration]); }, [showMinimap, isFirstSegmentInMinimap, events, segmentDuration]);

View File

@ -113,7 +113,10 @@ function useDraggableHandler({
} }
}); });
if (setHandlebarTime) { if (setHandlebarTime) {
setHandlebarTime(timelineStart - segmentIndex * segmentDuration); setHandlebarTime(
timelineStart -
(newHandlePosition / segmentHeight) * segmentDuration
);
} }
} }
} }
@ -132,10 +135,10 @@ function useDraggableHandler({
// TODO: determine when we want to do this // TODO: determine when we want to do this
const handlebar = scrollTimeRef.current; const handlebar = scrollTimeRef.current;
if (handlebar && showHandlebar) { if (handlebar && showHandlebar) {
// handlebar.scrollIntoView({ handlebar.scrollIntoView({
// behavior: "smooth", behavior: "smooth",
// block: "center", block: "center",
// }); });
} }
}, []); }, []);

View File

@ -102,7 +102,7 @@ function UIPlayground() {
const contentRef = useRef<HTMLDivElement>(null); const contentRef = useRef<HTMLDivElement>(null);
const [mockEvents, setMockEvents] = useState<ReviewSegment[]>([]); const [mockEvents, setMockEvents] = useState<ReviewSegment[]>([]);
const [handlebarTime, setHandlebarTime] = useState( const [handlebarTime, setHandlebarTime] = useState(
Math.floor(Date.now() / 1000) - 7 * 60 Math.floor(Date.now() / 1000) - 15 * 60
); );
const onSelect = useCallback(({ items }: { items: string[] }) => { const onSelect = useCallback(({ items }: { items: string[] }) => {
@ -217,7 +217,16 @@ function UIPlayground() {
<Heading as="h4" className="my-5"> <Heading as="h4" className="my-5">
Timeline Timeline
</Heading> </Heading>
<p className="text-small">Handlebar timestamp: {handlebarTime}</p> <p className="text-small">
Handlebar timestamp: {handlebarTime} -&nbsp;
{new Date(handlebarTime * 1000).toLocaleTimeString([], {
hour: "2-digit",
minute: "2-digit",
month: "short",
day: "2-digit",
second: "2-digit",
})}
</p>
<p className="text-small"> <p className="text-small">
Handlebar is dragging: {isDragging ? "yes" : "no"} Handlebar is dragging: {isDragging ? "yes" : "no"}
</p> </p>

View File

@ -247,58 +247,74 @@ export default function DesktopEventView({
</div> </div>
</div> </div>
{hasUpdate && (
<Button
className="absolute top-14 left-[50%] -translate-x-[50%] z-30 bg-gray-400 text-white"
variant="secondary"
onClick={() => {
setHasUpdate(false);
pullLatestData();
}}
>
<LuRefreshCcw className="w-4 h-4 mr-2" />
New Items To Review
</Button>
)}
<div className="flex h-full overflow-hidden"> <div className="flex h-full overflow-hidden">
<div <div
ref={contentRef} ref={contentRef}
className="flex flex-1 flex-wrap content-start gap-2 overflow-y-auto no-scrollbar" className="flex flex-1 flex-wrap content-start gap-2 overflow-y-auto no-scrollbar"
> >
{currentItems ? ( {hasUpdate && (
currentItems.map((value, segIdx) => { <div className="absolute w-full z-30">
const lastRow = segIdx == reviewItems[severity].length - 1; <div className="flex justify-center items-center mr-[100px]">
const relevantPreview = Object.values( <Button
relevantPreviews || [] className={`${
).find( hasUpdate
(preview) => ? "animate-in slide-in-from-top duration-500"
preview.camera == value.camera && : "invisible"
preview.start < value.start_time && } text-center mt-5 mx-auto bg-gray-400 text-white`}
preview.end > value.end_time variant="secondary"
); onClick={() => {
setHasUpdate(false);
return ( pullLatestData();
<div if (contentRef.current) {
key={value.id} contentRef.current.scrollTo({
ref={lastRow ? lastReviewRef : minimapRef} top: 0,
data-start={value.start_time} behavior: "smooth",
});
}
}}
> >
<div className="h-[234px] aspect-video rounded-lg overflow-hidden"> <LuRefreshCcw className="w-4 h-4 mr-2" />
<PreviewThumbnailPlayer New Items To Review
review={value} </Button>
relevantPreview={relevantPreview} </div>
setReviewed={() => markItemAsReviewed(value.id)} </div>
onClick={() => onSelectReview(value.id)}
/>
</div>
{lastRow && !reachedEnd && <ActivityIndicator />}
</div>
);
})
) : (
<div ref={lastReviewRef} />
)} )}
<div className="w-full mr-4 md:grid md:grid-cols-3 3xl:grid-cols-4 gap-4 overflow-y-auto no-scrollbar">
{currentItems ? (
currentItems.map((value, segIdx) => {
const lastRow = segIdx == reviewItems[severity].length - 1;
const relevantPreview = Object.values(
relevantPreviews || []
).find(
(preview) =>
preview.camera == value.camera &&
preview.start < value.start_time &&
preview.end > value.end_time
);
return (
<div
key={value.id}
ref={lastRow ? lastReviewRef : minimapRef}
data-start={value.start_time}
>
<div className="aspect-video rounded-lg overflow-hidden">
<PreviewThumbnailPlayer
review={value}
relevantPreview={relevantPreview}
setReviewed={() => markItemAsReviewed(value.id)}
onClick={() => onSelectReview(value.id)}
/>
</div>
{lastRow && !reachedEnd && <ActivityIndicator />}
</div>
);
})
) : (
<div ref={lastReviewRef} />
)}
</div>
</div> </div>
<div className="md:w-[100px] overflow-y-auto no-scrollbar"> <div className="md:w-[100px] overflow-y-auto no-scrollbar">
<EventReviewTimeline <EventReviewTimeline