From fe5f94aaeb3ad610e035584a53afc4f235a86d5a Mon Sep 17 00:00:00 2001 From: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com> Date: Mon, 16 Dec 2024 12:23:55 -0600 Subject: [PATCH] frontend --- web/src/api/ws.tsx | 16 +++++- .../settings/NotificationsSettingsView.tsx | 56 ++++++++++++++++++- 2 files changed, 69 insertions(+), 3 deletions(-) diff --git a/web/src/api/ws.tsx b/web/src/api/ws.tsx index 0c47d49f0..ac633b08b 100644 --- a/web/src/api/ws.tsx +++ b/web/src/api/ws.tsx @@ -53,13 +53,16 @@ function useValue(): useValueReturn { const cameraStates: WsState = {}; Object.entries(cameraActivity).forEach(([name, state]) => { - const { record, detect, snapshots, audio, autotracking } = + const { record, detect, snapshots, audio, notifications, autotracking } = // @ts-expect-error we know this is correct state["config"]; cameraStates[`${name}/recordings/state`] = record ? "ON" : "OFF"; cameraStates[`${name}/detect/state`] = detect ? "ON" : "OFF"; cameraStates[`${name}/snapshots/state`] = snapshots ? "ON" : "OFF"; cameraStates[`${name}/audio/state`] = audio ? "ON" : "OFF"; + cameraStates[`${name}/notifications/state`] = notifications + ? "ON" + : "OFF"; cameraStates[`${name}/ptz_autotracker/state`] = autotracking ? "ON" : "OFF"; @@ -414,6 +417,17 @@ export function useTrackedObjectUpdate(): { payload: string } { return useDeepMemo(JSON.parse(payload as string)); } +export function useNotifications(camera: string): { + payload: ToggleableSetting; + send: (payload: string, retain?: boolean) => void; +} { + const { + value: { payload }, + send, + } = useWs(`${camera}/notifications/state`, `${camera}/notifications/set`); + return { payload: payload as ToggleableSetting, send }; +} + export function useNotificationTest(): { payload: string; send: (payload: string, retain?: boolean) => void; diff --git a/web/src/views/settings/NotificationsSettingsView.tsx b/web/src/views/settings/NotificationsSettingsView.tsx index 51206ed68..75c56b567 100644 --- a/web/src/views/settings/NotificationsSettingsView.tsx +++ b/web/src/views/settings/NotificationsSettingsView.tsx @@ -1,4 +1,3 @@ -import { useNotificationTest } from "@/api/ws"; import ActivityIndicator from "@/components/indicators/activity-indicator"; import { Button } from "@/components/ui/button"; import { @@ -20,13 +19,15 @@ import { StatusBarMessagesContext } from "@/context/statusbar-provider"; import { FrigateConfig } from "@/types/frigateConfig"; import { zodResolver } from "@hookform/resolvers/zod"; import axios from "axios"; -import { useCallback, useContext, useEffect, useState } from "react"; +import { useCallback, useContext, useEffect, useMemo, useState } from "react"; import { useForm } from "react-hook-form"; import { LuExternalLink } from "react-icons/lu"; import { Link } from "react-router-dom"; import { toast } from "sonner"; import useSWR from "swr"; import { z } from "zod"; +import { useNotifications, useNotificationTest } from "@/api/ws"; +import FilterSwitch from "@/components/filter/FilterSwitch"; const NOTIFICATION_SERVICE_WORKER = "notifications-worker.js"; @@ -48,6 +49,16 @@ export default function NotificationView({ }, ); + const cameras = useMemo(() => { + if (!config) { + return []; + } + + return Object.values(config.cameras) + .filter((conf) => conf.ui.dashboard && conf.enabled) + .sort((aConf, bConf) => aConf.ui.order - bConf.ui.order); + }, [config]); + const { send: sendTestNotification } = useNotificationTest(); // status bar @@ -351,8 +362,49 @@ export default function NotificationView({ )} + {registration != null && ( +
Enable / disable notifications for specific cameras.
+