diff --git a/frigate/comms/webpush.py b/frigate/comms/webpush.py index f518a2d94..a858f9eac 100644 --- a/frigate/comms/webpush.py +++ b/frigate/comms/webpush.py @@ -371,13 +371,14 @@ class WebPushClient(Communicator): sorted_objects.update(payload["after"]["data"]["sub_labels"]) - title = f"{titlecase(', '.join(sorted_objects).replace('_', ' '))}{' was' if state == 'end' else ''} detected in {titlecase(', '.join(payload['after']['data']['zones']).replace('_', ' '))}" image = f"{payload['after']['thumb_path'].replace('/media/frigate', '')}" ended = state == "end" or state == "genai" if state == "genai" and payload["after"]["data"]["metadata"]: + title = payload["after"]["data"]["metadata"]["title"] message = payload["after"]["data"]["metadata"]["scene"] else: + title = f"{titlecase(', '.join(sorted_objects).replace('_', ' '))}{' was' if state == 'end' else ''} detected in {titlecase(', '.join(payload['after']['data']['zones']).replace('_', ' '))}" message = f"Detected on {camera_name}" if ended: diff --git a/web/src/components/card/ReviewCard.tsx b/web/src/components/card/ReviewCard.tsx index d3f3b6d24..b1e7a7b57 100644 --- a/web/src/components/card/ReviewCard.tsx +++ b/web/src/components/card/ReviewCard.tsx @@ -6,7 +6,7 @@ import { getIconForLabel } from "@/utils/iconUtil"; import { isDesktop, isIOS, isSafari } from "react-device-detect"; import useSWR from "swr"; import TimeAgo from "../dynamic/TimeAgo"; -import { useCallback, useMemo, useRef, useState } from "react"; +import { useCallback, useRef, useState } from "react"; import useImageLoaded from "@/hooks/use-image-loaded"; import ImageLoadingIndicator from "../indicators/ImageLoadingIndicator"; import { FaCompactDisc } from "react-icons/fa"; @@ -36,15 +36,16 @@ import { Tooltip, TooltipContent, TooltipTrigger } from "../ui/tooltip"; import { capitalizeFirstLetter } from "@/utils/stringUtil"; import { buttonVariants } from "../ui/button"; import { Trans, useTranslation } from "react-i18next"; +import { cn } from "@/lib/utils"; type ReviewCardProps = { event: ReviewSegment; - currentTime: number; + activeReviewItem?: ReviewSegment; onClick?: () => void; }; export default function ReviewCard({ event, - currentTime, + activeReviewItem, onClick, }: ReviewCardProps) { const { t } = useTranslation(["components/dialog"]); @@ -57,12 +58,6 @@ export default function ReviewCard({ : t("time.formattedTimestampHourMinute.12hour", { ns: "common" }), config?.ui.timezone, ); - const isSelected = useMemo( - () => - event.start_time <= currentTime && - (event.end_time ?? Date.now() / 1000) >= currentTime, - [event, currentTime], - ); const [optionsOpen, setOptionsOpen] = useState(false); const [deleteDialogOpen, setDeleteDialogOpen] = useState(false); @@ -139,7 +134,12 @@ export default function ReviewCard({ /> diff --git a/web/src/views/recording/RecordingView.tsx b/web/src/views/recording/RecordingView.tsx index 6ae284cd7..522dac370 100644 --- a/web/src/views/recording/RecordingView.tsx +++ b/web/src/views/recording/RecordingView.tsx @@ -466,9 +466,9 @@ export function RecordingView({ return mainCameraReviewItems.find( (rev) => - rev.start_time < currentTime && + rev.start_time - REVIEW_PADDING < currentTime && rev.end_time && - currentTime < rev.end_time, + currentTime < rev.end_time + REVIEW_PADDING, ); }, [config, currentTime, mainCameraReviewItems, mainCamera]); const onAnalysisOpen = useCallback( @@ -678,10 +678,12 @@ export function RecordingView({ : Math.max(1, getCameraAspect(mainCamera) ?? 0), }} > - + {isDesktop && ( + + )} @@ -792,12 +796,14 @@ type TimelineProps = { timelineType: TimelineType; timeRange: TimeRange; mainCameraReviewItems: ReviewSegment[]; + activeReviewItem?: ReviewSegment; currentTime: number; exportRange?: TimeRange; setCurrentTime: React.Dispatch>; manuallySetCurrentTime: (time: number, force: boolean) => void; setScrubbing: React.Dispatch>; setExportRange: (range: TimeRange) => void; + onAnalysisOpen: (open: boolean) => void; }; function Timeline({ contentRef, @@ -806,12 +812,14 @@ function Timeline({ timelineType, timeRange, mainCameraReviewItems, + activeReviewItem, currentTime, exportRange, setCurrentTime, manuallySetCurrentTime, setScrubbing, setExportRange, + onAnalysisOpen, }: TimelineProps) { const { t } = useTranslation(["views/events"]); const internalTimelineRef = useRef(null); @@ -889,12 +897,17 @@ function Timeline({ return ( + {isMobile && ( + + )} + {timelineType == "timeline" ? ( @@ -946,7 +959,7 @@ function Timeline({ { manuallySetCurrentTime( review.start_time - REVIEW_PADDING,