mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-02-08 20:25:26 +03:00
outline and scroll when segment is clicked
This commit is contained in:
parent
cfe4dc59b7
commit
e3ffdcc6f0
@ -1,7 +1,13 @@
|
|||||||
import { useEventUtils } from "@/hooks/use-event-utils";
|
import { useEventUtils } from "@/hooks/use-event-utils";
|
||||||
import { useSegmentUtils } from "@/hooks/use-segment-utils";
|
import { useSegmentUtils } from "@/hooks/use-segment-utils";
|
||||||
import { ReviewSegment, ReviewSeverity } from "@/types/review";
|
import { ReviewSegment, ReviewSeverity } from "@/types/review";
|
||||||
import React, { RefObject, useEffect, useMemo, useRef } from "react";
|
import React, {
|
||||||
|
RefObject,
|
||||||
|
useCallback,
|
||||||
|
useEffect,
|
||||||
|
useMemo,
|
||||||
|
useRef,
|
||||||
|
} from "react";
|
||||||
|
|
||||||
type EventSegmentProps = {
|
type EventSegmentProps = {
|
||||||
events: ReviewSegment[];
|
events: ReviewSegment[];
|
||||||
@ -139,6 +145,7 @@ export function EventSegment({
|
|||||||
getReviewed,
|
getReviewed,
|
||||||
displaySeverityType,
|
displaySeverityType,
|
||||||
shouldShowRoundedCorners,
|
shouldShowRoundedCorners,
|
||||||
|
getEventStart,
|
||||||
} = useSegmentUtils(segmentDuration, events, severityType);
|
} = useSegmentUtils(segmentDuration, events, severityType);
|
||||||
|
|
||||||
const { alignDateToTimeline } = useEventUtils(events, segmentDuration);
|
const { alignDateToTimeline } = useEventUtils(events, segmentDuration);
|
||||||
@ -155,6 +162,13 @@ export function EventSegment({
|
|||||||
() => shouldShowRoundedCorners(segmentTime),
|
() => shouldShowRoundedCorners(segmentTime),
|
||||||
[shouldShowRoundedCorners, segmentTime]
|
[shouldShowRoundedCorners, segmentTime]
|
||||||
);
|
);
|
||||||
|
const startTimestamp = useMemo(() => {
|
||||||
|
const eventStart = getEventStart(segmentTime);
|
||||||
|
if (eventStart) {
|
||||||
|
console.log("event start: " + new Date(eventStart * 1000));
|
||||||
|
return alignDateToTimeline(eventStart);
|
||||||
|
}
|
||||||
|
}, [getEventStart, segmentTime]);
|
||||||
|
|
||||||
const timestamp = useMemo(() => new Date(segmentTime * 1000), [segmentTime]);
|
const timestamp = useMemo(() => new Date(segmentTime * 1000), [segmentTime]);
|
||||||
const segmentKey = useMemo(() => segmentTime, [segmentTime]);
|
const segmentKey = useMemo(() => segmentTime, [segmentTime]);
|
||||||
@ -231,6 +245,26 @@ export function EventSegment({
|
|||||||
: "from-severity_alert-dimmed to-severity_alert",
|
: "from-severity_alert-dimmed to-severity_alert",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const segmentClick = useCallback(() => {
|
||||||
|
if (contentRef.current && startTimestamp) {
|
||||||
|
console.log(new Date(startTimestamp * 1000));
|
||||||
|
const element = contentRef.current.querySelector(
|
||||||
|
`[data-segment-start="${startTimestamp - segmentDuration}"]`
|
||||||
|
);
|
||||||
|
if (element instanceof HTMLElement) {
|
||||||
|
debounceScrollIntoView(element);
|
||||||
|
element.classList.add("outline-4", "shadow-[0_0_6px_1px]");
|
||||||
|
element.classList.remove("outline-0", "shadow-none");
|
||||||
|
|
||||||
|
// Remove the classes after a short timeout
|
||||||
|
setTimeout(() => {
|
||||||
|
element.classList.remove("outline-4", "shadow-[0_0_6px_1px]");
|
||||||
|
element.classList.add("outline-0", "shadow-none");
|
||||||
|
}, 3000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [startTimestamp]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div key={segmentKey} className={segmentClasses}>
|
<div key={segmentKey} className={segmentClasses}>
|
||||||
<MinimapBounds
|
<MinimapBounds
|
||||||
@ -272,14 +306,7 @@ export function EventSegment({
|
|||||||
${severityColors[severityValue]}
|
${severityColors[severityValue]}
|
||||||
`}
|
`}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (contentRef.current) {
|
segmentClick();
|
||||||
const element = contentRef.current.querySelector(
|
|
||||||
`[data-segment-start="${segmentTime}"]`
|
|
||||||
);
|
|
||||||
if (element instanceof HTMLElement) {
|
|
||||||
debounceScrollIntoView(element);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}}
|
}}
|
||||||
></div>
|
></div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -156,6 +156,21 @@ export const useSegmentUtils = (
|
|||||||
[events, getSegmentStart, getSegmentEnd, segmentDuration, severityType]
|
[events, getSegmentStart, getSegmentEnd, segmentDuration, severityType]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const getEventStart = useCallback(
|
||||||
|
(time: number): number => {
|
||||||
|
const matchingEvent = events.find((event) => {
|
||||||
|
return (
|
||||||
|
time >= getSegmentStart(event.start_time) &&
|
||||||
|
time < getSegmentEnd(event.end_time) &&
|
||||||
|
event.severity == severityType
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
return matchingEvent?.start_time ?? 0;
|
||||||
|
},
|
||||||
|
[events, getSegmentStart, getSegmentEnd, severityType]
|
||||||
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
getSegmentStart,
|
getSegmentStart,
|
||||||
getSegmentEnd,
|
getSegmentEnd,
|
||||||
@ -163,5 +178,6 @@ export const useSegmentUtils = (
|
|||||||
displaySeverityType,
|
displaySeverityType,
|
||||||
getReviewed,
|
getReviewed,
|
||||||
shouldShowRoundedCorners,
|
shouldShowRoundedCorners,
|
||||||
|
getEventStart,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@ -281,7 +281,7 @@ export default function DesktopEventView({
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
<div
|
<div
|
||||||
className="w-full mr-4 md:grid md:grid-cols-3 3xl:grid-cols-4 gap-4"
|
className="w-full mx-2 my-2 md:grid md:grid-cols-3 3xl:grid-cols-4 gap-4"
|
||||||
ref={contentRef}
|
ref={contentRef}
|
||||||
>
|
>
|
||||||
{currentItems ? (
|
{currentItems ? (
|
||||||
@ -304,6 +304,7 @@ export default function DesktopEventView({
|
|||||||
data-segment-start={
|
data-segment-start={
|
||||||
alignDateToTimeline(value.start_time) - segmentDuration
|
alignDateToTimeline(value.start_time) - segmentDuration
|
||||||
}
|
}
|
||||||
|
className="outline outline-destructive outline-offset-1 outline-0 rounded-lg shadow-none shadow-destructive transition-all duration-500"
|
||||||
>
|
>
|
||||||
<div className="aspect-video rounded-lg overflow-hidden">
|
<div className="aspect-video rounded-lg overflow-hidden">
|
||||||
<PreviewThumbnailPlayer
|
<PreviewThumbnailPlayer
|
||||||
@ -322,7 +323,7 @@ export default function DesktopEventView({
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="md:w-[100px] overflow-y-auto no-scrollbar">
|
<div className="md:w-[100px] mt-2 overflow-y-auto no-scrollbar">
|
||||||
<EventReviewTimeline
|
<EventReviewTimeline
|
||||||
segmentDuration={segmentDuration}
|
segmentDuration={segmentDuration}
|
||||||
timestampSpread={15}
|
timestampSpread={15}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user