From a6aa5328aa0805847f955a779127eb0e8c36e3e2 Mon Sep 17 00:00:00 2001 From: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com> Date: Thu, 22 Feb 2024 21:15:50 -0600 Subject: [PATCH] UI fixes (#9986) * scroll minimap to keep it in view * remove console log * change ref * rebase to dev * rebase to dev * rebase to dev * fix history flexbox and live extra scrollbar * remove extra class --- web/src/components/timeline/EventSegment.tsx | 23 ++- web/src/hooks/use-handle-dragging.ts | 13 +- web/src/pages/Live.tsx | 2 +- web/src/pages/UIPlayground.tsx | 203 +++++++++++-------- web/src/views/events/DesktopEventView.tsx | 102 +++++----- 5 files changed, 204 insertions(+), 139 deletions(-) diff --git a/web/src/components/timeline/EventSegment.tsx b/web/src/components/timeline/EventSegment.tsx index 8d3507079..8493bca40 100644 --- a/web/src/components/timeline/EventSegment.tsx +++ b/web/src/components/timeline/EventSegment.tsx @@ -1,7 +1,7 @@ import { useEventUtils } from "@/hooks/use-event-utils"; import { useSegmentUtils } from "@/hooks/use-segment-utils"; import { ReviewSegment, ReviewSeverity } from "@/types/review"; -import React, { useMemo } from "react"; +import React, { useEffect, useMemo, useRef } from "react"; type EventSegmentProps = { events: ReviewSegment[]; @@ -19,6 +19,7 @@ type MinimapSegmentProps = { isLastSegmentInMinimap: boolean; alignedMinimapStartTime: number; alignedMinimapEndTime: number; + firstMinimapSegmentRef: React.MutableRefObject; }; type TickSegmentProps = { @@ -41,11 +42,15 @@ function MinimapBounds({ isLastSegmentInMinimap, alignedMinimapStartTime, alignedMinimapEndTime, + firstMinimapSegmentRef, }: MinimapSegmentProps) { return ( <> {isFirstSegmentInMinimap && ( -
+
{new Date(alignedMinimapStartTime * 1000).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit", @@ -179,6 +184,19 @@ export function EventSegment({ return showMinimap && segmentTime === alignedMinimapEndTime; }, [showMinimap, segmentTime, alignedMinimapEndTime]); + const firstMinimapSegmentRef = useRef(null); + + useEffect(() => { + // Check if the first segment is out of view + const firstSegment = firstMinimapSegmentRef.current; + if (firstSegment && showMinimap && isFirstSegmentInMinimap) { + firstSegment.scrollIntoView({ + behavior: "smooth", + block: "center", + }); + } + }, [showMinimap, isFirstSegmentInMinimap, events, segmentDuration]); + const segmentClasses = `flex flex-row ${ showMinimap ? isInMinimapRange @@ -212,6 +230,7 @@ export function EventSegment({ isLastSegmentInMinimap={isLastSegmentInMinimap} alignedMinimapStartTime={alignedMinimapStartTime} alignedMinimapEndTime={alignedMinimapEndTime} + firstMinimapSegmentRef={firstMinimapSegmentRef} /> ; @@ -128,6 +128,17 @@ function useDraggableHandler({ ] ); + useEffect(() => { + // TODO: determine when we want to do this + const handlebar = scrollTimeRef.current; + if (handlebar && showHandlebar) { + // handlebar.scrollIntoView({ + // behavior: "smooth", + // block: "center", + // }); + } + }, []); + return { handleMouseDown, handleMouseUp, handleMouseMove }; } diff --git a/web/src/pages/Live.tsx b/web/src/pages/Live.tsx index ed66a8e38..3dd48114f 100644 --- a/web/src/pages/Live.tsx +++ b/web/src/pages/Live.tsx @@ -79,7 +79,7 @@ function Live() { }, []); return ( -
+
{events && events.length > 0 && ( diff --git a/web/src/pages/UIPlayground.tsx b/web/src/pages/UIPlayground.tsx index 056dd87e8..f7bc5da47 100644 --- a/web/src/pages/UIPlayground.tsx +++ b/web/src/pages/UIPlayground.tsx @@ -61,7 +61,8 @@ function eventsToScrubberItems(events: Event[]): ScrubberItem[] { } const generateRandomEvent = (): ReviewSegment => { - const start_time = Math.floor(Date.now() / 1000) - Math.random() * 60 * 60; + const start_time = + Math.floor(Date.now() / 1000) - 10800 - Math.random() * 60 * 60; const end_time = Math.floor(start_time + Math.random() * 60 * 10); const severities: ReviewSeverity[] = [ "significant_motion", @@ -123,6 +124,23 @@ function UIPlayground() { setMockEvents(initialEvents); }, []); + // Calculate minimap start and end times based on events + const minimapStartTime = useMemo(() => { + if (mockEvents && mockEvents.length > 0) { + return Math.min(...mockEvents.map((event) => event.start_time)); + } + return Math.floor(Date.now() / 1000); // Default to current time if no events + }, [events]); + + const minimapEndTime = useMemo(() => { + if (mockEvents && mockEvents.length > 0) { + return Math.max( + ...mockEvents.map((event) => event.end_time ?? event.start_time) + ); + } + return Math.floor(Date.now() / 1000); // Default to current time if no events + }, [events]); + const [zoomLevel, setZoomLevel] = useState(0); const [zoomSettings, setZoomSettings] = useState({ segmentDuration: 60, @@ -150,101 +168,114 @@ function UIPlayground() { setZoomSettings(possibleZoomLevels[nextZoomLevel]); } + const [isDragging, setIsDragging] = useState(false); + + const handleDraggingChange = (dragging: boolean) => { + setIsDragging(dragging); + }; + return ( <> - UI Playground +
+
+
+ UI Playground - - Scrubber - -

- Shows the 10 most recent events within the last 4 hours -

- - {!config && } - - {config && ( -
- {events && events.length > 0 && ( - <> - - - )} -
- )} - - {config && ( -
- {timeline && ( - <> - - - )} -
- )} - -
-
-
- Timeline - -

Handlebar timestamp: {handlebarTime}

-

- - -

- - Color scheme + Scrubber

- Colors as set by the current theme. See the{" "} - - shadcn theming docs - {" "} - for usage. + Shows the 10 most recent events within the last 4 hours

-
- {colors.map((color, index) => ( - - ))} + {!config && } + + {config && ( +
+ {events && events.length > 0 && ( + <> + + + )} +
+ )} + + {config && ( +
+ {timeline && ( + <> + + + )} +
+ )} + +
+ + Timeline + +

Handlebar timestamp: {handlebarTime}

+

+ Handlebar is dragging: {isDragging ? "yes" : "no"} +

+

+ + +

+ + Color scheme + +

+ Colors as set by the current theme. See the{" "} + + shadcn theming docs + {" "} + for usage. +

+ +
+ {colors.map((color, index) => ( + + ))} +
-
-
- + +
+ +
diff --git a/web/src/views/events/DesktopEventView.tsx b/web/src/views/events/DesktopEventView.tsx index 052c125c0..02e8a8854 100644 --- a/web/src/views/events/DesktopEventView.tsx +++ b/web/src/views/events/DesktopEventView.tsx @@ -195,8 +195,8 @@ export default function DesktopEventView({ } return ( -
-
+
+
)} -
- {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 - ); +
+
+ {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 ( -
-
- markItemAsReviewed(value.id)} - onClick={() => onSelectReview(value.id)} - /> + return ( +
+
+ markItemAsReviewed(value.id)} + onClick={() => onSelectReview(value.id)} + /> +
+ {lastRow && !reachedEnd && }
- {lastRow && !reachedEnd && } -
- ); - }) - ) : ( -
- )} -
-
- + ); + }) + ) : ( +
+ )} +
+
+ +
);