Skip to content

Commit

Permalink
Persist selected camera group for live (#10448)
Browse files Browse the repository at this point in the history
* Persist camera group selected

* Cleanup
  • Loading branch information
NickM-27 authored Mar 14, 2024
1 parent a660e3a commit 2decdea
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 9 deletions.
8 changes: 3 additions & 5 deletions web/src/components/filter/CameraGroupSelector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,8 @@ import {
import { isDesktop } from "react-device-detect";
import useSWR from "swr";
import { MdHome } from "react-icons/md";
import useOverlayState from "@/hooks/use-overlay-state";
import { usePersistedOverlayState } from "@/hooks/use-overlay-state";
import { Button } from "../ui/button";
import { useNavigate } from "react-router-dom";
import { useCallback, useMemo, useState } from "react";
import { Tooltip, TooltipContent, TooltipTrigger } from "../ui/tooltip";
import { getIconForGroup } from "@/utils/iconUtil";
Expand All @@ -31,7 +30,6 @@ type CameraGroupSelectorProps = {
};
export function CameraGroupSelector({ className }: CameraGroupSelectorProps) {
const { data: config } = useSWR<FrigateConfig>("config");
const navigate = useNavigate();

// tooltip

Expand All @@ -54,7 +52,7 @@ export function CameraGroupSelector({ className }: CameraGroupSelectorProps) {

// groups

const [group, setGroup] = useOverlayState("cameraGroup");
const [group, setGroup] = usePersistedOverlayState("cameraGroup");

const groups = useMemo(() => {
if (!config) {
Expand Down Expand Up @@ -89,7 +87,7 @@ export function CameraGroupSelector({ className }: CameraGroupSelectorProps) {
: "text-muted-foreground bg-secondary focus:text-muted-foreground focus:bg-secondary"
}
size="xs"
onClick={() => (group ? navigate(-1) : null)}
onClick={() => (group ? setGroup(undefined, true) : null)}
onMouseEnter={() => (isDesktop ? showTooltip("home") : null)}
onMouseLeave={() => (isDesktop ? showTooltip(undefined) : null)}
>
Expand Down
36 changes: 36 additions & 0 deletions web/src/hooks/use-overlay-state.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { useCallback, useMemo } from "react";
import { useLocation, useNavigate } from "react-router-dom";
import { usePersistence } from "./use-persistence";

export default function useOverlayState<S extends string>(
key: string,
Expand Down Expand Up @@ -27,3 +28,38 @@ export default function useOverlayState<S extends string>(

return [overlayStateValue ?? defaultValue, setOverlayStateValue];
}

export function usePersistedOverlayState<S extends string>(
key: string,
defaultValue: S | undefined = undefined,
): [S | undefined, (value: S | undefined, replace?: boolean) => void] {
const [persistedValue, setPersistedValue] = usePersistence<S>(
key,
defaultValue,
);
const location = useLocation();
const navigate = useNavigate();
const currentLocationState = location.state;

const setOverlayStateValue = useCallback(
(value: S | undefined, replace: boolean = false) => {
setPersistedValue(value);
const newLocationState = { ...currentLocationState };
newLocationState[key] = value;
navigate(location.pathname, { state: newLocationState, replace });
},
// we know that these deps are correct
// eslint-disable-next-line react-hooks/exhaustive-deps
[key, navigate],
);

const overlayStateValue = useMemo<S | undefined>(
() => location.state && location.state[key],
[location, key],
);

return [
overlayStateValue ?? persistedValue ?? defaultValue,
setOverlayStateValue,
];
}
4 changes: 2 additions & 2 deletions web/src/hooks/use-persistence.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { get as getData, set as setData } from "idb-keyval";

type usePersistenceReturn<S> = [
value: S | undefined,
setValue: (value: S) => void,
setValue: (value: S | undefined) => void,
loaded: boolean,
];

Expand All @@ -15,7 +15,7 @@ export function usePersistence<S>(
const [loaded, setLoaded] = useState<boolean>(false);

const setValue = useCallback(
(value: S) => {
(value: S | undefined) => {
setInternalValue(value);
async function update() {
await setData(key, value);
Expand Down
6 changes: 4 additions & 2 deletions web/src/pages/Live.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import useOverlayState from "@/hooks/use-overlay-state";
import useOverlayState, {
usePersistedOverlayState,
} from "@/hooks/use-overlay-state";
import { FrigateConfig } from "@/types/frigateConfig";
import LiveCameraView from "@/views/live/LiveCameraView";
import LiveDashboardView from "@/views/live/LiveDashboardView";
Expand All @@ -9,7 +11,7 @@ function Live() {
const { data: config } = useSWR<FrigateConfig>("config");

const [selectedCameraName, setSelectedCameraName] = useOverlayState("camera");
const [cameraGroup] = useOverlayState("cameraGroup");
const [cameraGroup] = usePersistedOverlayState("cameraGroup");

const includesBirdseye = useMemo(() => {
if (config && cameraGroup) {
Expand Down

0 comments on commit 2decdea

Please sign in to comment.