diff --git a/web/src/views/recording/RecordingView.tsx b/web/src/views/recording/RecordingView.tsx index 3b001cb16..bde6c6d43 100644 --- a/web/src/views/recording/RecordingView.tsx +++ b/web/src/views/recording/RecordingView.tsx @@ -11,6 +11,7 @@ import DetailStream from "@/components/timeline/DetailStream"; import { Button } from "@/components/ui/button"; import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"; import { useOverlayState } from "@/hooks/use-overlay-state"; +import { useResizeObserver } from "@/hooks/resize-observer"; import { ExportMode } from "@/types/filter"; import { FrigateConfig } from "@/types/frigateConfig"; import { Preview } from "@/types/preview"; @@ -31,12 +32,7 @@ import { useRef, useState, } from "react"; -import { - isDesktop, - isMobile, - isMobileOnly, - isTablet, -} from "react-device-detect"; +import { isDesktop, isMobile } from "react-device-detect"; import { IoMdArrowRoundBack } from "react-icons/io"; import { useNavigate } from "react-router-dom"; import { Toaster } from "@/components/ui/sonner"; @@ -55,7 +51,6 @@ import { RecordingSegment, RecordingStartingPoint, } from "@/types/record"; -import { useResizeObserver } from "@/hooks/resize-observer"; import { cn } from "@/lib/utils"; import { useFullscreen } from "@/hooks/use-fullscreen"; import { useTimezone } from "@/hooks/use-date-utils"; @@ -399,49 +394,47 @@ export function RecordingView({ } }, [mainCameraAspect]); - const [{ width: mainWidth, height: mainHeight }] = + // use a resize observer to determine whether to use w-full or h-full based on container aspect ratio + const [{ width: containerWidth, height: containerHeight }] = useResizeObserver(cameraLayoutRef); + const [{ width: previewRowWidth, height: previewRowHeight }] = + useResizeObserver(previewRowRef); - const mainCameraStyle = useMemo(() => { - if (isMobile || mainCameraAspect != "normal" || !config) { - return undefined; + const useHeightBased = useMemo(() => { + if (!containerWidth || !containerHeight) { + return false; } - const camera = config.cameras[mainCamera]; - - if (!camera) { - return undefined; + const cameraAspectRatio = getCameraAspect(mainCamera); + if (!cameraAspectRatio) { + return false; } - const aspect = getCameraAspect(mainCamera); + // Calculate available space for camera after accounting for preview row + // For tall cameras: preview row is side-by-side (takes width) + // For wide/normal cameras: preview row is stacked (takes height) + const availableWidth = + mainCameraAspect == "tall" && previewRowWidth + ? containerWidth - previewRowWidth + : containerWidth; + const availableHeight = + mainCameraAspect != "tall" && previewRowHeight + ? containerHeight - previewRowHeight + : containerHeight; - if (!aspect) { - return undefined; - } + const availableAspectRatio = availableWidth / availableHeight; - const availableHeight = mainHeight - 112; - - let percent; - if (mainWidth / availableHeight < aspect) { - percent = 100; - } else { - const availableWidth = aspect * availableHeight; - percent = - (mainWidth < availableWidth - ? mainWidth / availableWidth - : availableWidth / mainWidth) * 100; - } - - return { - width: `${Math.round(percent)}%`, - }; + // If available space is wider than camera aspect, constrain by height (h-full) + // If available space is taller than camera aspect, constrain by width (w-full) + return availableAspectRatio >= cameraAspectRatio; }, [ - config, - mainCameraAspect, - mainWidth, - mainHeight, - mainCamera, + containerWidth, + containerHeight, + previewRowWidth, + previewRowHeight, getCameraAspect, + mainCamera, + mainCameraAspect, ]); const previewRowOverflows = useMemo(() => { @@ -685,19 +678,17 @@ export function RecordingView({