diff --git a/web/src/components/timeline/DetailStream.tsx b/web/src/components/timeline/DetailStream.tsx index 73e0cf530..0632b10b9 100644 --- a/web/src/components/timeline/DetailStream.tsx +++ b/web/src/components/timeline/DetailStream.tsx @@ -5,7 +5,10 @@ import { getLifecycleItemDescription } from "@/utils/lifecycleUtil"; import { useDetailStream } from "@/context/detail-stream-context"; import scrollIntoView from "scroll-into-view-if-needed"; import useUserInteraction from "@/hooks/use-user-interaction"; -import { formatUnixTimestampToDateTime } from "@/utils/dateUtil"; +import { + formatUnixTimestampToDateTime, + formatSecondsToDuration, +} from "@/utils/dateUtil"; import { useTranslation } from "react-i18next"; import AnnotationOffsetSlider from "@/components/overlay/detail/AnnotationOffsetSlider"; import { FrigateConfig } from "@/types/frigateConfig"; @@ -13,7 +16,7 @@ import useSWR from "swr"; import ActivityIndicator from "../indicators/activity-indicator"; import { Event } from "@/types/event"; import { getIconForLabel } from "@/utils/iconUtil"; -import { ReviewSegment, REVIEW_PADDING } from "@/types/review"; +import { ReviewSegment } from "@/types/review"; import { Collapsible, CollapsibleTrigger, @@ -49,7 +52,6 @@ export default function DetailStream({ }); const effectiveTime = currentTime + annotationOffset / 1000; - const PAD = 0; // REVIEW_PADDING ?? 2; const [upload, setUpload] = useState(undefined); // Ensure we initialize the active review when reviewItems first arrive. @@ -64,8 +66,8 @@ export default function DetailStream({ let closest: { r: ReviewSegment; diff: number } | undefined; for (const r of reviewItems) { - const start = (r.start_time ?? 0) - PAD; - const end = (r.end_time ?? r.start_time ?? start) + PAD; + const start = r.start_time ?? 0; + const end = r.end_time ?? r.start_time ?? start; if (effectiveTime >= start && effectiveTime <= end) { target = r; break; @@ -78,12 +80,12 @@ export default function DetailStream({ if (!target && closest) target = closest.r; if (target) { - const start = (target.start_time ?? 0) - PAD; + const start = target.start_time ?? 0; setActiveReviewId( `review-${target.id ?? target.start_time ?? Math.floor(start)}`, ); } - }, [reviewItems, activeReviewId, effectiveTime, PAD]); + }, [reviewItems, activeReviewId, effectiveTime]); // Auto-scroll to current time useEffect(() => { @@ -99,8 +101,8 @@ export default function DetailStream({ let closest: { r: ReviewSegment; diff: number } | undefined; for (const r of items) { - const start = (r.start_time ?? 0) - PAD; - const end = (r.end_time ?? r.start_time ?? start) + PAD; + const start = r.start_time ?? 0; + const end = r.end_time ?? r.start_time ?? start; if (effectiveTime >= start && effectiveTime <= end) { target = r; break; @@ -113,7 +115,7 @@ export default function DetailStream({ if (!target && closest) target = closest.r; if (target) { - const start = (target.start_time ?? 0) - PAD; + const start = target.start_time ?? 0; const id = `review-${target.id ?? target.start_time ?? Math.floor(start)}`; const element = scrollRef.current.querySelector( `[data-review-id="${id}"]`, @@ -132,15 +134,14 @@ export default function DetailStream({ annotationOffset, userInteracting, setProgrammaticScroll, - PAD, ]); // Auto-select active review based on effectiveTime (if inside a review range) useEffect(() => { if (!reviewItems || reviewItems.length === 0) return; for (const r of reviewItems) { - const start = (r.start_time ?? 0) - PAD; - const end = (r.end_time ?? r.start_time ?? start) + PAD; + const start = r.start_time ?? 0; + const end = r.end_time ?? r.start_time ?? start; if (effectiveTime >= start && effectiveTime <= end) { setActiveReviewId( `review-${r.id ?? r.start_time ?? Math.floor(start)}`, @@ -148,7 +149,7 @@ export default function DetailStream({ return; } } - }, [effectiveTime, reviewItems, PAD]); + }, [effectiveTime, reviewItems]); if (!config) { return ; @@ -173,7 +174,7 @@ export default function DetailStream({ ) : ( reviewItems?.map((review: ReviewSegment) => { - const id = `review-${review.id ?? review.start_time ?? Math.floor((review.start_time ?? 0) - PAD)}`; + const id = `review-${review.id ?? review.start_time ?? Math.floor(review.start_time ?? 0)}`; return (
{displayTime}
+ {reviewDuration && ( +
+ {reviewDuration} +
+ )}
{reviewInfo}
@@ -398,7 +407,7 @@ function EventCollapsible({ event.id != selectedObjectId && (effectiveTime ?? 0) >= (event.start_time ?? 0) && (effectiveTime ?? 0) <= (event.end_time ?? event.start_time ?? 0) && - "bg-secondary outline-[1px] -outline-offset-[0.8px] outline-primary/40", + "bg-secondary-highlight outline-[1.5px] -outline-offset-[1.1px] outline-primary/40", )} >
diff --git a/web/themes/theme-default.css b/web/themes/theme-default.css index d5e0a0b80..b96f2ecca 100644 --- a/web/themes/theme-default.css +++ b/web/themes/theme-default.css @@ -36,8 +36,8 @@ --secondary-foreground: hsl(222.2, 17.4%, 36.2%); --secondary-foreground: 222.2 17.4% 36.2%; - --secondary-highlight: hsl(0, 0%, 94%); - --secondary-highlight: 0 0% 94%; + --secondary-highlight: hsl(210, 17.4%, 94%); + --secondary-highlight: 210 17.4% 94%; --neutral: hsl(0, 0%, 45.1%); --neutral: 0 0% 45.1%;