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 { useEffect, useMemo, useRef, useState } 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"; export default function LiveBirdseyeView() { const { data: config } = useSWR("config"); const navigate = useNavigate(); const { isPortrait } = useMobileOrientation(); const mainRef = useRef(null); const [{ width: windowWidth, height: windowHeight }] = useResizeObserver(window); // fullscreen state useEffect(() => { if (mainRef.current == null) { return; } const listener = () => { setFullscreen(document.fullscreenElement != null); }; document.addEventListener("fullscreenchange", listener); return () => { document.removeEventListener("fullscreenchange", listener); }; }, [mainRef]); // playback state const [fullscreen, setFullscreen] = useState(false); const cameraAspectRatio = useMemo(() => { if (!config) { return 16 / 9; } return config.birdseye.width / config.birdseye.height; }, [config]); const growClassName = useMemo(() => { if (isMobile) { if (isPortrait) { return "absolute left-2 right-2 top-[50%] -translate-y-[50%]"; } else { if (cameraAspectRatio > 16 / 9) { 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 > 16 / 9) { 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-2 bottom-2 left-[50%] -translate-x-[50%]"; } }, [cameraAspectRatio, fullscreen, isPortrait]); const preferredLiveMode = useMemo(() => { if (!config || !config.birdseye.restream) { return "jsmpeg"; } if (isSafari) { return "webrtc"; } return "mse"; }, [config]); const windowAspectRatio = useMemo(() => { return windowWidth / windowHeight; }, [windowWidth, windowHeight]); const aspectRatio = useMemo(() => { if (isMobile || fullscreen) { return cameraAspectRatio; } else { return windowAspectRatio < cameraAspectRatio ? windowAspectRatio - 0.05 : cameraAspectRatio - 0.03; } }, [cameraAspectRatio, windowAspectRatio, fullscreen]); if (!config) { return ; } return (
{!fullscreen ? ( ) : (
)}
{ if (fullscreen) { document.exitFullscreen(); } else { mainRef.current?.requestFullscreen(); } }} />
); }