diff --git a/web/src/components/timeline/segment-metadata.tsx b/web/src/components/timeline/segment-metadata.tsx index 3b91aaa56..f35ceb1c6 100644 --- a/web/src/components/timeline/segment-metadata.tsx +++ b/web/src/components/timeline/segment-metadata.tsx @@ -1,3 +1,6 @@ +import { FrigateConfig } from "@/types/frigateConfig"; +import useSWR from "swr"; + type MinimapSegmentProps = { isFirstSegmentInMinimap: boolean; isLastSegmentInMinimap: boolean; @@ -28,6 +31,8 @@ export function MinimapBounds({ firstMinimapSegmentRef, dense, }: MinimapSegmentProps) { + const { data: config } = useSWR("config"); + return ( <> {isFirstSegmentInMinimap && ( @@ -36,6 +41,7 @@ export function MinimapBounds({ ref={firstMinimapSegmentRef} > {new Date(alignedMinimapStartTime * 1000).toLocaleTimeString([], { + hour12: config?.ui.time_format != "24hour", hour: "2-digit", minute: "2-digit", ...(!dense && { month: "short", day: "2-digit" }), @@ -46,6 +52,7 @@ export function MinimapBounds({ {isLastSegmentInMinimap && (
{new Date(alignedMinimapEndTime * 1000).toLocaleTimeString([], { + hour12: config?.ui.time_format != "24hour", hour: "2-digit", minute: "2-digit", ...(!dense && { month: "short", day: "2-digit" }), @@ -83,6 +90,8 @@ export function Timestamp({ timestampSpread, segmentKey, }: TimestampSegmentProps) { + const { data: config } = useSWR("config"); + return (
{!isFirstSegmentInMinimap && !isLastSegmentInMinimap && ( @@ -93,6 +102,7 @@ export function Timestamp({ {timestamp.getMinutes() % timestampSpread === 0 && timestamp.getSeconds() === 0 && timestamp.toLocaleTimeString([], { + hour12: config?.ui.time_format != "24hour", hour: "2-digit", minute: "2-digit", })} diff --git a/web/src/hooks/use-draggable-element.ts b/web/src/hooks/use-draggable-element.ts index 8cc61d451..51b6a6a52 100644 --- a/web/src/hooks/use-draggable-element.ts +++ b/web/src/hooks/use-draggable-element.ts @@ -1,6 +1,8 @@ import { ReactNode, useCallback, useEffect, useMemo, useState } from "react"; import scrollIntoView from "scroll-into-view-if-needed"; import { useTimelineUtils } from "./use-timeline-utils"; +import { FrigateConfig } from "@/types/frigateConfig"; +import useSWR from "swr"; type DraggableElementProps = { contentRef: React.RefObject; @@ -49,6 +51,8 @@ function useDraggableElement({ dense, timelineSegments, }: DraggableElementProps) { + const { data: config } = useSWR("config"); + const [clientYPosition, setClientYPosition] = useState(null); const [initialClickAdjustment, setInitialClickAdjustment] = useState(0); const [elementScrollIntoView, setElementScrollIntoView] = useState(true); @@ -170,6 +174,7 @@ function useDraggableElement({ draggableElementTimeRef.current.textContent = new Date( segmentStartTime * 1000, ).toLocaleTimeString([], { + hour12: config?.ui.time_format != "24hour", hour: "2-digit", minute: "2-digit", ...(segmentDuration < 60 && !dense && { second: "2-digit" }), @@ -196,6 +201,7 @@ function useDraggableElement({ setDraggableElementTime, setDraggableElementPosition, dense, + config, ], ); diff --git a/web/src/views/events/EventView.tsx b/web/src/views/events/EventView.tsx index 5e35aef28..8e865316d 100644 --- a/web/src/views/events/EventView.tsx +++ b/web/src/views/events/EventView.tsx @@ -29,7 +29,7 @@ import { useRef, useState, } from "react"; -import { isDesktop, isMobile } from "react-device-detect"; +import { isDesktop, isMobile, isTablet } from "react-device-detect"; import { LuFolderCheck } from "react-icons/lu"; import { MdCircle } from "react-icons/md"; import useSWR from "swr"; @@ -48,6 +48,7 @@ import { Skeleton } from "@/components/ui/skeleton"; import scrollIntoView from "scroll-into-view-if-needed"; import { Toaster } from "@/components/ui/sonner"; import { toast } from "sonner"; +import { cn } from "@/lib/utils"; type EventViewProps = { reviewItems?: SegmentedReviewData; @@ -866,7 +867,12 @@ function MotionReview({
3 || isTablet || isDesktop) && + "grid-cols-2", + "gap-2 overflow-auto px-1 md:mx-2 md:gap-4 xl:grid-cols-3 3xl:grid-cols-4", + )} > {reviewCameras.map((camera) => { let grow; @@ -874,13 +880,12 @@ function MotionReview({ const aspectRatio = camera.detect.width / camera.detect.height; if (aspectRatio > 2) { grow = "aspect-wide"; - spans = "sm:col-span-2"; + spans = reviewCameras.length > 3 && "col-span-2"; } else if (aspectRatio < 1) { grow = "md:h-full aspect-tall"; - spans = "md:row-span-2"; + spans = "row-span-2"; } else { grow = "aspect-video"; - spans = ""; } const detectionType = getDetectionType(camera.name); return ( diff --git a/web/src/views/live/LiveDashboardView.tsx b/web/src/views/live/LiveDashboardView.tsx index ac7ffdebe..4d09e8b9c 100644 --- a/web/src/views/live/LiveDashboardView.tsx +++ b/web/src/views/live/LiveDashboardView.tsx @@ -243,9 +243,17 @@ export default function LiveDashboardView({ > {includeBirdseye && birdseyeConfig?.enabled && (
{ + const aspectRatio = + birdseyeConfig.width / birdseyeConfig.height; + if (aspectRatio > 2) { + return `${mobileLayout == "grid" && "col-span-2"} aspect-wide`; + } else if (aspectRatio < 1) { + return `${mobileLayout == "grid" && "row-span-2 md:h-full"} aspect-tall`; + } else { + return "aspect-video"; + } + })()} ref={birdseyeContainerRef} > 2) { - grow = `${mobileLayout == "grid" ? "col-span-2" : ""} aspect-wide`; + grow = `${mobileLayout == "grid" && "col-span-2"} aspect-wide`; } else if (aspectRatio < 1) { - grow = `${mobileLayout == "grid" ? "row-span-2 aspect-tall md:h-full" : ""} aspect-tall`; + grow = `${mobileLayout == "grid" && "row-span-2 md:h-full"} aspect-tall`; } else { grow = "aspect-video"; }