2025-02-10 00:13:32 +03:00
|
|
|
import React, {
|
|
|
|
|
useEffect,
|
|
|
|
|
useMemo,
|
|
|
|
|
useRef,
|
|
|
|
|
RefObject,
|
|
|
|
|
useCallback,
|
|
|
|
|
} from "react";
|
2024-03-18 23:58:54 +03:00
|
|
|
import { useTimelineUtils } from "@/hooks/use-timeline-utils";
|
2025-02-10 00:13:32 +03:00
|
|
|
import {
|
|
|
|
|
ReviewSegment,
|
|
|
|
|
ReviewSeverity,
|
|
|
|
|
TimelineZoomDirection,
|
2025-10-29 21:04:29 +03:00
|
|
|
ZoomLevel,
|
2025-02-10 00:13:32 +03:00
|
|
|
} from "@/types/review";
|
2024-03-04 19:42:51 +03:00
|
|
|
import ReviewTimeline from "./ReviewTimeline";
|
2025-02-10 00:13:32 +03:00
|
|
|
import {
|
|
|
|
|
VirtualizedEventSegments,
|
|
|
|
|
VirtualizedEventSegmentsRef,
|
|
|
|
|
} from "./VirtualizedEventSegments";
|
2024-02-21 02:22:59 +03:00
|
|
|
|
|
|
|
|
export type EventReviewTimelineProps = {
|
|
|
|
|
segmentDuration: number;
|
|
|
|
|
timestampSpread: number;
|
|
|
|
|
timelineStart: number;
|
2024-02-21 20:58:41 +03:00
|
|
|
timelineEnd: number;
|
2024-02-21 02:22:59 +03:00
|
|
|
showHandlebar?: boolean;
|
|
|
|
|
handlebarTime?: number;
|
2024-02-22 17:16:37 +03:00
|
|
|
setHandlebarTime?: React.Dispatch<React.SetStateAction<number>>;
|
2024-02-21 02:22:59 +03:00
|
|
|
showMinimap?: boolean;
|
|
|
|
|
minimapStartTime?: number;
|
|
|
|
|
minimapEndTime?: number;
|
2024-03-18 23:58:54 +03:00
|
|
|
showExportHandles?: boolean;
|
|
|
|
|
exportStartTime?: number;
|
|
|
|
|
exportEndTime?: number;
|
|
|
|
|
setExportStartTime?: React.Dispatch<React.SetStateAction<number>>;
|
|
|
|
|
setExportEndTime?: React.Dispatch<React.SetStateAction<number>>;
|
2024-02-21 02:22:59 +03:00
|
|
|
events: ReviewSegment[];
|
2024-03-21 20:49:04 +03:00
|
|
|
visibleTimestamps?: number[];
|
2024-02-21 02:22:59 +03:00
|
|
|
severityType: ReviewSeverity;
|
2024-03-21 05:56:15 +03:00
|
|
|
timelineRef?: RefObject<HTMLDivElement>;
|
2024-02-21 02:22:59 +03:00
|
|
|
contentRef: RefObject<HTMLDivElement>;
|
2024-02-23 03:03:34 +03:00
|
|
|
onHandlebarDraggingChange?: (isDragging: boolean) => void;
|
2025-02-10 00:13:32 +03:00
|
|
|
isZooming: boolean;
|
|
|
|
|
zoomDirection: TimelineZoomDirection;
|
2024-03-28 18:03:06 +03:00
|
|
|
dense?: boolean;
|
2025-10-29 21:04:29 +03:00
|
|
|
onZoomChange?: (newZoomLevel: number) => void;
|
|
|
|
|
possibleZoomLevels?: ZoomLevel[];
|
|
|
|
|
currentZoomLevel?: number;
|
2024-02-21 02:22:59 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export function EventReviewTimeline({
|
|
|
|
|
segmentDuration,
|
|
|
|
|
timestampSpread,
|
|
|
|
|
timelineStart,
|
2024-02-21 20:58:41 +03:00
|
|
|
timelineEnd,
|
2024-02-21 02:22:59 +03:00
|
|
|
showHandlebar = false,
|
|
|
|
|
handlebarTime,
|
2024-02-22 17:16:37 +03:00
|
|
|
setHandlebarTime,
|
2024-02-21 02:22:59 +03:00
|
|
|
showMinimap = false,
|
|
|
|
|
minimapStartTime,
|
|
|
|
|
minimapEndTime,
|
2024-03-18 23:58:54 +03:00
|
|
|
showExportHandles = false,
|
|
|
|
|
exportStartTime,
|
|
|
|
|
exportEndTime,
|
|
|
|
|
setExportStartTime,
|
|
|
|
|
setExportEndTime,
|
2024-02-21 02:22:59 +03:00
|
|
|
events,
|
2024-03-21 20:49:04 +03:00
|
|
|
visibleTimestamps,
|
2024-02-21 02:22:59 +03:00
|
|
|
severityType,
|
2024-03-21 05:56:15 +03:00
|
|
|
timelineRef,
|
2024-02-21 02:22:59 +03:00
|
|
|
contentRef,
|
2024-02-23 03:03:34 +03:00
|
|
|
onHandlebarDraggingChange,
|
2025-02-10 00:13:32 +03:00
|
|
|
isZooming,
|
|
|
|
|
zoomDirection,
|
2024-03-28 18:03:06 +03:00
|
|
|
dense = false,
|
2025-10-29 21:04:29 +03:00
|
|
|
onZoomChange,
|
|
|
|
|
possibleZoomLevels,
|
|
|
|
|
currentZoomLevel,
|
2024-02-21 02:22:59 +03:00
|
|
|
}: EventReviewTimelineProps) {
|
2024-03-21 05:56:15 +03:00
|
|
|
const internalTimelineRef = useRef<HTMLDivElement>(null);
|
2024-03-21 20:49:04 +03:00
|
|
|
const selectedTimelineRef = timelineRef || internalTimelineRef;
|
2025-02-10 00:13:32 +03:00
|
|
|
const virtualizedSegmentsRef = useRef<VirtualizedEventSegmentsRef>(null);
|
2024-03-18 23:58:54 +03:00
|
|
|
|
2024-02-21 20:58:41 +03:00
|
|
|
const timelineDuration = useMemo(
|
2024-02-21 23:07:32 +03:00
|
|
|
() => timelineStart - timelineEnd,
|
2024-02-29 01:23:56 +03:00
|
|
|
[timelineEnd, timelineStart],
|
2024-02-21 20:58:41 +03:00
|
|
|
);
|
2024-02-21 02:22:59 +03:00
|
|
|
|
2024-03-28 18:03:06 +03:00
|
|
|
const { alignStartDateToTimeline } = useTimelineUtils({
|
2024-03-18 23:58:54 +03:00
|
|
|
segmentDuration,
|
|
|
|
|
timelineDuration,
|
2024-03-21 20:49:04 +03:00
|
|
|
timelineRef: selectedTimelineRef,
|
2024-03-18 23:58:54 +03:00
|
|
|
});
|
|
|
|
|
|
2024-03-28 18:03:06 +03:00
|
|
|
const timelineStartAligned = useMemo(
|
|
|
|
|
() => alignStartDateToTimeline(timelineStart),
|
|
|
|
|
[timelineStart, alignStartDateToTimeline],
|
|
|
|
|
);
|
2024-02-21 02:22:59 +03:00
|
|
|
|
2025-02-10 00:13:32 +03:00
|
|
|
// Generate segment times for the timeline
|
|
|
|
|
const segmentTimes = useMemo(() => {
|
2024-03-27 00:36:28 +03:00
|
|
|
const segmentCount = Math.ceil(timelineDuration / segmentDuration);
|
2025-02-10 00:13:32 +03:00
|
|
|
return Array.from(
|
|
|
|
|
{ length: segmentCount },
|
|
|
|
|
(_, index) => timelineStartAligned - index * segmentDuration,
|
|
|
|
|
);
|
|
|
|
|
}, [timelineDuration, segmentDuration, timelineStartAligned]);
|
2024-02-21 02:22:59 +03:00
|
|
|
|
2024-03-21 20:49:04 +03:00
|
|
|
useEffect(() => {
|
|
|
|
|
if (
|
|
|
|
|
visibleTimestamps &&
|
2025-02-10 00:13:32 +03:00
|
|
|
visibleTimestamps.length > 0 &&
|
|
|
|
|
!showMinimap &&
|
|
|
|
|
virtualizedSegmentsRef.current
|
2024-03-21 20:49:04 +03:00
|
|
|
) {
|
|
|
|
|
const alignedVisibleTimestamps = visibleTimestamps.map(
|
|
|
|
|
alignStartDateToTimeline,
|
|
|
|
|
);
|
2025-02-10 00:13:32 +03:00
|
|
|
|
|
|
|
|
scrollToSegment(Math.max(...alignedVisibleTimestamps), true);
|
2024-03-21 20:49:04 +03:00
|
|
|
}
|
2024-05-13 15:42:11 +03:00
|
|
|
// don't scroll when segments update from unreviewed -> reviewed
|
|
|
|
|
// we know that these deps are correct
|
|
|
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
2024-03-21 20:49:04 +03:00
|
|
|
}, [
|
|
|
|
|
selectedTimelineRef,
|
|
|
|
|
showMinimap,
|
|
|
|
|
alignStartDateToTimeline,
|
|
|
|
|
visibleTimestamps,
|
2025-02-10 00:13:32 +03:00
|
|
|
segmentDuration,
|
2024-03-21 20:49:04 +03:00
|
|
|
]);
|
|
|
|
|
|
2025-02-10 00:13:32 +03:00
|
|
|
const scrollToSegment = useCallback(
|
|
|
|
|
(segmentTime: number, ifNeeded?: boolean, behavior?: ScrollBehavior) => {
|
|
|
|
|
if (virtualizedSegmentsRef.current) {
|
|
|
|
|
virtualizedSegmentsRef.current.scrollToSegment(
|
|
|
|
|
segmentTime,
|
|
|
|
|
ifNeeded,
|
|
|
|
|
behavior,
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
[],
|
|
|
|
|
);
|
|
|
|
|
|
2024-02-21 02:22:59 +03:00
|
|
|
return (
|
2024-03-04 19:42:51 +03:00
|
|
|
<ReviewTimeline
|
2024-03-21 20:49:04 +03:00
|
|
|
timelineRef={selectedTimelineRef}
|
2024-03-28 18:03:06 +03:00
|
|
|
contentRef={contentRef}
|
2024-03-04 19:42:51 +03:00
|
|
|
segmentDuration={segmentDuration}
|
2024-03-18 23:58:54 +03:00
|
|
|
timelineDuration={timelineDuration}
|
2024-03-28 18:03:06 +03:00
|
|
|
timelineStartAligned={timelineStartAligned}
|
2024-03-04 19:42:51 +03:00
|
|
|
showHandlebar={showHandlebar}
|
2024-03-28 18:03:06 +03:00
|
|
|
onHandlebarDraggingChange={onHandlebarDraggingChange}
|
2024-03-18 23:58:54 +03:00
|
|
|
showExportHandles={showExportHandles}
|
2024-03-28 18:03:06 +03:00
|
|
|
handlebarTime={handlebarTime}
|
|
|
|
|
setHandlebarTime={setHandlebarTime}
|
|
|
|
|
exportStartTime={exportStartTime}
|
|
|
|
|
exportEndTime={exportEndTime}
|
|
|
|
|
setExportStartTime={setExportStartTime}
|
|
|
|
|
setExportEndTime={setExportEndTime}
|
|
|
|
|
dense={dense}
|
2025-02-10 00:13:32 +03:00
|
|
|
segments={segmentTimes}
|
|
|
|
|
scrollToSegment={scrollToSegment}
|
|
|
|
|
isZooming={isZooming}
|
|
|
|
|
zoomDirection={zoomDirection}
|
2025-10-29 21:04:29 +03:00
|
|
|
onZoomChange={onZoomChange}
|
|
|
|
|
possibleZoomLevels={possibleZoomLevels}
|
|
|
|
|
currentZoomLevel={currentZoomLevel}
|
2024-02-28 16:18:08 +03:00
|
|
|
>
|
2025-02-10 00:13:32 +03:00
|
|
|
<VirtualizedEventSegments
|
|
|
|
|
ref={virtualizedSegmentsRef}
|
|
|
|
|
timelineRef={selectedTimelineRef}
|
|
|
|
|
segments={segmentTimes}
|
|
|
|
|
events={events}
|
|
|
|
|
segmentDuration={segmentDuration}
|
|
|
|
|
timestampSpread={timestampSpread}
|
|
|
|
|
showMinimap={showMinimap}
|
|
|
|
|
minimapStartTime={minimapStartTime}
|
|
|
|
|
minimapEndTime={minimapEndTime}
|
|
|
|
|
severityType={severityType}
|
|
|
|
|
contentRef={contentRef}
|
|
|
|
|
setHandlebarTime={setHandlebarTime}
|
|
|
|
|
dense={dense}
|
|
|
|
|
alignStartDateToTimeline={alignStartDateToTimeline}
|
|
|
|
|
/>
|
2024-03-04 19:42:51 +03:00
|
|
|
</ReviewTimeline>
|
2024-02-21 02:22:59 +03:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export default EventReviewTimeline;
|