import CameraFeatureToggle from "@/components/dynamic/CameraFeatureToggle"; import ActivityIndicator from "@/components/indicators/activity-indicator"; import BirdseyeLivePlayer from "@/components/player/BirdseyeLivePlayer"; import { Button } from "@/components/ui/button"; import { TooltipProvider } from "@/components/ui/tooltip"; import { useResizeObserver } from "@/hooks/resize-observer"; import { FrigateConfig } from "@/types/frigateConfig"; import { useMemo, useRef } from "react"; import { isDesktop, isMobile, isSafari, useMobileOrientation, } from "react-device-detect"; import { FaCompress, FaExpand } from "react-icons/fa"; import { IoMdArrowBack } from "react-icons/io"; import { useNavigate } from "react-router-dom"; import { TransformWrapper, TransformComponent } from "react-zoom-pan-pinch"; import useSWR from "swr"; type LiveBirdseyeViewProps = { fullscreen: boolean; toggleFullscreen: () => void; }; export default function LiveBirdseyeView({ fullscreen, toggleFullscreen, }: LiveBirdseyeViewProps) { const { data: config } = useSWR("config"); const navigate = useNavigate(); const { isPortrait } = useMobileOrientation(); const mainRef = useRef(null); const containerRef = useRef(null); const [{ width: windowWidth, height: windowHeight }] = useResizeObserver(window); // playback state const cameraAspectRatio = useMemo(() => { if (!config) { return 16 / 9; } return config.birdseye.width / config.birdseye.height; }, [config]); const windowAspectRatio = useMemo(() => { return windowWidth / windowHeight; }, [windowWidth, windowHeight]); const containerAspectRatio = useMemo(() => { if (!containerRef.current) { return windowAspectRatio ?? 0; } return containerRef.current.clientWidth / containerRef.current.clientHeight; }, [windowAspectRatio, containerRef]); const constrainedAspectRatio = useMemo(() => { if (isMobile || fullscreen) { return cameraAspectRatio; } else { return containerAspectRatio < cameraAspectRatio ? containerAspectRatio : cameraAspectRatio; } }, [cameraAspectRatio, containerAspectRatio, fullscreen]); const growClassName = useMemo(() => { if (isMobile) { if (isPortrait) { return "absolute left-2 right-2 top-[50%] -translate-y-[50%]"; } else { if (cameraAspectRatio > containerAspectRatio) { return "absolute left-0 top-[50%] -translate-y-[50%]"; } else { return "absolute top-2 bottom-2 left-[50%] -translate-x-[50%]"; } } } if (fullscreen) { if (cameraAspectRatio > containerAspectRatio) { return "absolute inset-x-2 top-[50%] -translate-y-[50%]"; } else { return "absolute inset-y-2 left-[50%] -translate-x-[50%]"; } } else { return "absolute top-0 bottom-0 left-[50%] -translate-x-[50%]"; } }, [cameraAspectRatio, containerAspectRatio, fullscreen, isPortrait]); const preferredLiveMode = useMemo(() => { if (!config || !config.birdseye.restream) { return "jsmpeg"; } if (isSafari) { return "webrtc"; } return "mse"; }, [config]); if (!config) { return ; } return (
{!fullscreen ? ( ) : (
)}
); }