diff --git a/web/src/components/camera/DebugCameraImage.tsx b/web/src/components/camera/DebugCameraImage.tsx index e7352c17a..34588aa06 100644 --- a/web/src/components/camera/DebugCameraImage.tsx +++ b/web/src/components/camera/DebugCameraImage.tsx @@ -22,7 +22,7 @@ export default function DebugCameraImage({ cameraConfig, }: DebugCameraImageProps) { const [showSettings, setShowSettings] = useState(false); - const [options, setOptions] = usePersistence( + const [options, setOptions] = usePersistence( `${cameraConfig?.name}-feed`, emptyObject ); @@ -36,7 +36,7 @@ export default function DebugCameraImage({ const searchParams = useMemo( () => new URLSearchParams( - Object.keys(options).reduce((memo, key) => { + Object.keys(options || {}).reduce((memo, key) => { //@ts-ignore we know this is correct memo.push([key, options[key] === true ? "1" : "0"]); return memo; @@ -68,7 +68,7 @@ export default function DebugCameraImage({ diff --git a/web/src/hooks/use-camera-live-mode.ts b/web/src/hooks/use-camera-live-mode.ts index 214713dc1..f13622556 100644 --- a/web/src/hooks/use-camera-live-mode.ts +++ b/web/src/hooks/use-camera-live-mode.ts @@ -7,7 +7,7 @@ import { LivePlayerMode } from "@/types/live"; export default function useCameraLiveMode( cameraConfig: CameraConfig, preferredMode?: string -): LivePlayerMode { +): LivePlayerMode | undefined { const { data: config } = useSWR("config"); const restreamEnabled = useMemo(() => { @@ -22,10 +22,10 @@ export default function useCameraLiveMode( ) ); }, [config, cameraConfig]); - const defaultLiveMode = useMemo(() => { + const defaultLiveMode = useMemo(() => { if (config && cameraConfig) { if (restreamEnabled) { - return cameraConfig.ui.live_mode || config?.ui.live_mode; + return cameraConfig.ui.live_mode || config.ui.live_mode; } return "jsmpeg"; @@ -33,7 +33,7 @@ export default function useCameraLiveMode( return undefined; }, [cameraConfig, restreamEnabled]); - const [viewSource] = usePersistence( + const [viewSource] = usePersistence( `${cameraConfig.name}-source`, defaultLiveMode ); diff --git a/web/src/hooks/use-persistence.ts b/web/src/hooks/use-persistence.ts index 48a03d7e1..3d61cfa17 100644 --- a/web/src/hooks/use-persistence.ts +++ b/web/src/hooks/use-persistence.ts @@ -1,21 +1,21 @@ import { useEffect, useState, useCallback } from "react"; import { get as getData, set as setData } from "idb-keyval"; -type usePersistenceReturn = [ - value: any | undefined, - setValue: (value: string | boolean) => void, +type usePersistenceReturn = [ + value: S | undefined, + setValue: (value: S) => void, loaded: boolean, ]; -export function usePersistence( +export function usePersistence( key: string, - defaultValue: any | undefined = undefined -): usePersistenceReturn { - const [value, setInternalValue] = useState(defaultValue); + defaultValue: S | undefined = undefined +): usePersistenceReturn { + const [value, setInternalValue] = useState(defaultValue); const [loaded, setLoaded] = useState(false); const setValue = useCallback( - (value: string | boolean) => { + (value: S) => { setInternalValue(value); async function update() { await setData(key, value); diff --git a/web/src/pages/Events.tsx b/web/src/pages/Events.tsx index f3d185c16..fc821a06f 100644 --- a/web/src/pages/Events.tsx +++ b/web/src/pages/Events.tsx @@ -28,9 +28,10 @@ export default function Events() { // review paging + const [beforeTs, setBeforeTs] = useState(Date.now() / 1000); const last24Hours = useMemo(() => { - return { before: Date.now() / 1000, after: getHoursAgo(24) }; - }, []); + return { before: beforeTs, after: getHoursAgo(24) }; + }, [beforeTs]); const selectedTimeRange = useMemo(() => { if (reviewSearchParams["after"] == undefined) { return last24Hours; @@ -73,7 +74,7 @@ export default function Events() { }; return ["review", params]; }, - [reviewSearchParams] + [reviewSearchParams, last24Hours] ); const { @@ -96,10 +97,7 @@ export default function Events() { setSize(size + 1); }, [size]); - const reloadData = useCallback(() => { - setSize(1); - updateSegments(); - }, []); + const reloadData = useCallback(() => setBeforeTs(Date.now() / 1000), []); // preview videos diff --git a/web/src/pages/Live.tsx b/web/src/pages/Live.tsx index cb6ada236..e4c9f71a2 100644 --- a/web/src/pages/Live.tsx +++ b/web/src/pages/Live.tsx @@ -5,6 +5,7 @@ import LivePlayer from "@/components/player/LivePlayer"; import { Button } from "@/components/ui/button"; import { ScrollArea, ScrollBar } from "@/components/ui/scroll-area"; import { TooltipProvider } from "@/components/ui/tooltip"; +import { usePersistence } from "@/hooks/use-persistence"; import { Event as FrigateEvent } from "@/types/event"; import { FrigateConfig } from "@/types/frigateConfig"; import { useCallback, useEffect, useMemo, useState } from "react"; @@ -17,7 +18,8 @@ function Live() { // layout - const [layout, setLayout] = useState<"grid" | "list">( + const [layout, setLayout] = usePersistence<"grid" | "list">( + "live-layout", isDesktop ? "grid" : "list" ); diff --git a/web/src/pages/Logs.tsx b/web/src/pages/Logs.tsx index f912ed3b5..591fe30f9 100644 --- a/web/src/pages/Logs.tsx +++ b/web/src/pages/Logs.tsx @@ -97,8 +97,9 @@ function Logs() { {!endVisible && ( -
contentRef.current?.scrollTo({ top: contentRef.current?.scrollHeight, @@ -107,7 +108,7 @@ function Logs() { } > Jump to Bottom -
+ )}
- + {isMobile && ( + + )} - + {filter?.before == undefined && ( + + )} - {reachedEnd && currentItems == null && ( + {!isValidating && currentItems == null && (
There are no {severity} items to review @@ -287,9 +291,9 @@ export default function EventView({
); }) - ) : ( + ) : severity != "alert" ? (
- )} + ) : null}