From 398ad2e6cc39dafa8ad7ea596adfc63318e0d3fd Mon Sep 17 00:00:00 2001 From: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com> Date: Sat, 17 Aug 2024 12:40:39 -0500 Subject: [PATCH] refactor camera live mode hook --- web/src/hooks/use-camera-live-mode.ts | 86 +++++++++++++--------- web/src/views/live/DraggableGridLayout.tsx | 35 +-------- web/src/views/live/LiveDashboardView.tsx | 57 +------------- 3 files changed, 58 insertions(+), 120 deletions(-) diff --git a/web/src/hooks/use-camera-live-mode.ts b/web/src/hooks/use-camera-live-mode.ts index 2a1997045..edf165951 100644 --- a/web/src/hooks/use-camera-live-mode.ts +++ b/web/src/hooks/use-camera-live-mode.ts @@ -1,49 +1,65 @@ import { CameraConfig, FrigateConfig } from "@/types/frigateConfig"; -import { useMemo } from "react"; +import { useCallback, useEffect, useState } from "react"; import useSWR from "swr"; -import { usePersistence } from "./use-persistence"; import { LivePlayerMode } from "@/types/live"; export default function useCameraLiveMode( - cameraConfig: CameraConfig, - preferredMode?: LivePlayerMode, -): LivePlayerMode | undefined { + cameras: CameraConfig[], + windowVisible: boolean, +) { const { data: config } = useSWR("config"); + const [preferredLiveModes, setPreferredLiveModes] = useState<{ + [key: string]: LivePlayerMode; + }>({}); - const restreamEnabled = useMemo(() => { - if (!config) { - return false; - } + useEffect(() => { + if (!cameras) return; - return ( - cameraConfig && - Object.keys(config.go2rtc.streams || {}).includes( - cameraConfig.live.stream_name, - ) + const mseSupported = + "MediaSource" in window || "ManagedMediaSource" in window; + + const newPreferredLiveModes = cameras.reduce( + (acc, camera) => { + const isRestreamed = + config && + Object.keys(config.go2rtc.streams || {}).includes( + camera.live.stream_name, + ); + + if (!mseSupported) { + acc[camera.name] = isRestreamed ? "webrtc" : "jsmpeg"; + } else { + acc[camera.name] = isRestreamed ? "mse" : "jsmpeg"; + } + return acc; + }, + {} as { [key: string]: LivePlayerMode }, ); - }, [config, cameraConfig]); - const defaultLiveMode = useMemo(() => { - if (config) { - if (restreamEnabled) { - return preferredMode || "mse"; - } - return "jsmpeg"; - } + setPreferredLiveModes(newPreferredLiveModes); + }, [cameras, config, windowVisible]); - return undefined; - }, [config, preferredMode, restreamEnabled]); - const [viewSource] = usePersistence( - `${cameraConfig.name}-source`, - defaultLiveMode, + const resetPreferredLiveMode = useCallback( + (cameraName: string) => { + const mseSupported = + "MediaSource" in window || "ManagedMediaSource" in window; + const isRestreamed = + config && Object.keys(config.go2rtc.streams || {}).includes(cameraName); + + setPreferredLiveModes((prevModes) => { + const newModes = { ...prevModes }; + + if (!mseSupported) { + newModes[cameraName] = isRestreamed ? "webrtc" : "jsmpeg"; + } else { + newModes[cameraName] = isRestreamed ? "mse" : "jsmpeg"; + } + + return newModes; + }); + }, + [config], ); - if ( - restreamEnabled && - (preferredMode == "mse" || preferredMode == "webrtc") - ) { - return preferredMode; - } else { - return viewSource; - } + return { preferredLiveModes, setPreferredLiveModes, resetPreferredLiveMode }; } diff --git a/web/src/views/live/DraggableGridLayout.tsx b/web/src/views/live/DraggableGridLayout.tsx index 2234c0c91..fc2d9bb52 100644 --- a/web/src/views/live/DraggableGridLayout.tsx +++ b/web/src/views/live/DraggableGridLayout.tsx @@ -41,6 +41,7 @@ import { TooltipContent, } from "@/components/ui/tooltip"; import { Toaster } from "@/components/ui/sonner"; +import useCameraLiveMode from "@/hooks/use-camera-live-mode"; type DraggableGridLayoutProps = { cameras: CameraConfig[]; @@ -55,7 +56,6 @@ type DraggableGridLayoutProps = { setIsEditMode: React.Dispatch>; fullscreen: boolean; toggleFullscreen: () => void; - resetPreferredLiveMode: (camera: string) => void; }; export default function DraggableGridLayout({ cameras, @@ -70,43 +70,14 @@ export default function DraggableGridLayout({ setIsEditMode, fullscreen, toggleFullscreen, - resetPreferredLiveMode, }: DraggableGridLayoutProps) { const { data: config } = useSWR("config"); const birdseyeConfig = useMemo(() => config?.birdseye, [config]); // preferred live modes per camera - const [preferredLiveModes, setPreferredLiveModes] = useState<{ - [key: string]: LivePlayerMode; - }>({}); - - useEffect(() => { - if (!cameras) return; - - const mseSupported = - "MediaSource" in window || "ManagedMediaSource" in window; - - const newPreferredLiveModes = cameras.reduce( - (acc, camera) => { - const isRestreamed = - config && - Object.keys(config.go2rtc.streams || {}).includes( - camera.live.stream_name, - ); - - if (!mseSupported) { - acc[camera.name] = isRestreamed ? "webrtc" : "jsmpeg"; - } else { - acc[camera.name] = isRestreamed ? "mse" : "jsmpeg"; - } - return acc; - }, - {} as { [key: string]: LivePlayerMode }, - ); - - setPreferredLiveModes(newPreferredLiveModes); - }, [cameras, config, windowVisible]); + const { preferredLiveModes, setPreferredLiveModes, resetPreferredLiveMode } = + useCameraLiveMode(cameras, windowVisible); const ResponsiveGridLayout = useMemo(() => WidthProvider(Responsive), []); diff --git a/web/src/views/live/LiveDashboardView.tsx b/web/src/views/live/LiveDashboardView.tsx index af32fae73..54a6138c0 100644 --- a/web/src/views/live/LiveDashboardView.tsx +++ b/web/src/views/live/LiveDashboardView.tsx @@ -28,10 +28,11 @@ import DraggableGridLayout from "./DraggableGridLayout"; import { IoClose } from "react-icons/io5"; import { LuLayoutDashboard } from "react-icons/lu"; import { cn } from "@/lib/utils"; -import { LivePlayerError, LivePlayerMode } from "@/types/live"; +import { LivePlayerError } from "@/types/live"; import { FaCompress, FaExpand } from "react-icons/fa"; import { useResizeObserver } from "@/hooks/resize-observer"; import useKeyboardListener from "@/hooks/use-keyboard-listener"; +import useCameraLiveMode from "@/hooks/use-camera-live-mode"; type LiveDashboardViewProps = { cameras: CameraConfig[]; @@ -130,9 +131,6 @@ export default function LiveDashboardView({ // camera live views const [autoLiveView] = usePersistence("autoLiveView", true); - const [preferredLiveModes, setPreferredLiveModes] = useState<{ - [key: string]: LivePlayerMode; - }>({}); const [{ height: containerHeight }] = useResizeObserver(containerRef); @@ -187,54 +185,8 @@ export default function LiveDashboardView({ }; }, []); - useEffect(() => { - if (!cameras) return; - - const mseSupported = - "MediaSource" in window || "ManagedMediaSource" in window; - - const newPreferredLiveModes = cameras.reduce( - (acc, camera) => { - const isRestreamed = - config && - Object.keys(config.go2rtc.streams || {}).includes( - camera.live.stream_name, - ); - - if (!mseSupported) { - acc[camera.name] = isRestreamed ? "webrtc" : "jsmpeg"; - } else { - acc[camera.name] = isRestreamed ? "mse" : "jsmpeg"; - } - return acc; - }, - {} as { [key: string]: LivePlayerMode }, - ); - - setPreferredLiveModes(newPreferredLiveModes); - }, [cameras, config, windowVisible]); - - const resetPreferredLiveMode = useCallback( - (cameraName: string) => { - const mseSupported = - "MediaSource" in window || "ManagedMediaSource" in window; - const isRestreamed = - config && Object.keys(config.go2rtc.streams || {}).includes(cameraName); - - setPreferredLiveModes((prevModes) => { - const newModes = { ...prevModes }; - - if (!mseSupported) { - newModes[cameraName] = isRestreamed ? "webrtc" : "jsmpeg"; - } else { - newModes[cameraName] = isRestreamed ? "mse" : "jsmpeg"; - } - - return newModes; - }); - }, - [config], - ); + const { preferredLiveModes, setPreferredLiveModes, resetPreferredLiveMode } = + useCameraLiveMode(cameras, windowVisible); const cameraRef = useCallback( (node: HTMLElement | null) => { @@ -465,7 +417,6 @@ export default function LiveDashboardView({ setIsEditMode={setIsEditMode} fullscreen={fullscreen} toggleFullscreen={toggleFullscreen} - resetPreferredLiveMode={resetPreferredLiveMode} /> )}