Motion review timeline (#10235)

* initial motion and audio timeline with dummy data

* initial motion and audio timeline with dummy data
This commit is contained in:
Josh Hawkins
2024-03-04 10:42:51 -06:00
committed by GitHub
parent 0f168dfc1a
commit 282c92c9c8
11 changed files with 862 additions and 188 deletions

View File

@@ -1,6 +1,6 @@
import { useApiHost } from "@/api";
import { useEventUtils } from "@/hooks/use-event-utils";
import { useSegmentUtils } from "@/hooks/use-segment-utils";
import { useEventSegmentUtils } from "@/hooks/use-event-segment-utils";
import { ReviewSegment, ReviewSeverity } from "@/types/review";
import React, {
RefObject,
@@ -9,7 +9,6 @@ import React, {
useMemo,
useRef,
} from "react";
import { isDesktop } from "react-device-detect";
import {
HoverCard,
HoverCardContent,
@@ -17,6 +16,7 @@ import {
} from "../ui/hover-card";
import { HoverCardPortal } from "@radix-ui/react-hover-card";
import scrollIntoView from "scroll-into-view-if-needed";
import { MinimapBounds, Tick, Timestamp } from "./segment-metadata";
type EventSegmentProps = {
events: ReviewSegment[];
@@ -30,105 +30,6 @@ type EventSegmentProps = {
contentRef: RefObject<HTMLDivElement>;
};
type MinimapSegmentProps = {
isFirstSegmentInMinimap: boolean;
isLastSegmentInMinimap: boolean;
alignedMinimapStartTime: number;
alignedMinimapEndTime: number;
firstMinimapSegmentRef: React.MutableRefObject<HTMLDivElement | null>;
};
type TickSegmentProps = {
timestamp: Date;
timestampSpread: number;
};
type TimestampSegmentProps = {
isFirstSegmentInMinimap: boolean;
isLastSegmentInMinimap: boolean;
timestamp: Date;
timestampSpread: number;
segmentKey: number;
};
function MinimapBounds({
isFirstSegmentInMinimap,
isLastSegmentInMinimap,
alignedMinimapStartTime,
alignedMinimapEndTime,
firstMinimapSegmentRef,
}: MinimapSegmentProps) {
return (
<>
{isFirstSegmentInMinimap && (
<div
className="absolute inset-0 -bottom-7 w-full flex items-center justify-center text-primary-foreground font-medium z-20 text-center text-[10px] scroll-mt-8"
ref={firstMinimapSegmentRef}
>
{new Date(alignedMinimapStartTime * 1000).toLocaleTimeString([], {
hour: "2-digit",
minute: "2-digit",
...(isDesktop && { month: "short", day: "2-digit" }),
})}
</div>
)}
{isLastSegmentInMinimap && (
<div className="absolute inset-0 -top-3 w-full flex items-center justify-center text-primary-foreground font-medium z-20 text-center text-[10px]">
{new Date(alignedMinimapEndTime * 1000).toLocaleTimeString([], {
hour: "2-digit",
minute: "2-digit",
...(isDesktop && { month: "short", day: "2-digit" }),
})}
</div>
)}
</>
);
}
function Tick({ timestamp, timestampSpread }: TickSegmentProps) {
return (
<div className="absolute">
<div className="flex items-end content-end w-[12px] h-2">
<div
className={`h-0.5 ${
timestamp.getMinutes() % timestampSpread === 0 &&
timestamp.getSeconds() === 0
? "w-[12px] bg-gray-400"
: "w-[8px] bg-gray-600"
}`}
></div>
</div>
</div>
);
}
function Timestamp({
isFirstSegmentInMinimap,
isLastSegmentInMinimap,
timestamp,
timestampSpread,
segmentKey,
}: TimestampSegmentProps) {
return (
<div className="absolute left-[15px] top-[1px] h-2 z-10">
{!isFirstSegmentInMinimap && !isLastSegmentInMinimap && (
<div
key={`${segmentKey}_timestamp`}
className="text-[8px] text-gray-400"
>
{timestamp.getMinutes() % timestampSpread === 0 &&
timestamp.getSeconds() === 0 &&
timestamp.toLocaleTimeString([], {
hour: "2-digit",
minute: "2-digit",
})}
</div>
)}
</div>
);
}
export function EventSegment({
events,
segmentTime,
@@ -147,7 +48,7 @@ export function EventSegment({
shouldShowRoundedCorners,
getEventStart,
getEventThumbnail,
} = useSegmentUtils(segmentDuration, events, severityType);
} = useEventSegmentUtils(segmentDuration, events, severityType);
const { alignStartDateToTimeline, alignEndDateToTimeline } = useEventUtils(
events,
@@ -294,11 +195,7 @@ export function EventSegment({
}, [startTimestamp]);
return (
<div
key={segmentKey}
className={segmentClasses}
data-segment-time={new Date(segmentTime * 1000)}
>
<div key={segmentKey} className={segmentClasses}>
<MinimapBounds
isFirstSegmentInMinimap={isFirstSegmentInMinimap}
isLastSegmentInMinimap={isLastSegmentInMinimap}
@@ -317,7 +214,7 @@ export function EventSegment({
segmentKey={segmentKey}
/>
{severity.map((severityValue, index) => (
{severity.map((severityValue: number, index: number) => (
<React.Fragment key={index}>
{severityValue === displaySeverityType && (
<HoverCard openDelay={200} closeDelay={100}>