diff --git a/web/src/hooks/use-api-filter.ts b/web/src/hooks/use-api-filter.ts index bffbff7e8..f9baead6e 100644 --- a/web/src/hooks/use-api-filter.ts +++ b/web/src/hooks/use-api-filter.ts @@ -47,9 +47,9 @@ export default function useApiFilter< return [filter, setFilter, searchParams]; } -export function useApiFilterArgs< - F extends FilterType, ->(): useApiFilterReturn { +export function useApiFilterArgs( + arrayKeys: string[], +): useApiFilterReturn { const [rawParams, setRawParams] = useSearchParams(); const setFilter = useCallback( @@ -64,30 +64,37 @@ export function useApiFilterArgs< const filter: { [key: string]: unknown } = {}; - rawParams.forEach((value, key) => { - const isValidNumber = /^-?\d+(\.\d+)?(?!.)/.test(value); - const isValidEventID = /^\d+\.\d+-[a-zA-Z0-9]+$/.test(value); + // always treat these keys as string[], not as a number or event id + const arrayKeySet = new Set(arrayKeys); - if ( - value != "true" && - value != "false" && - !isValidNumber && - !isValidEventID - ) { + rawParams.forEach((value, key) => { + if (arrayKeySet.has(key)) { filter[key] = value.includes(",") ? value.split(",") : [value]; } else { - if (value != undefined) { - try { - filter[key] = JSON.parse(value); - } catch { - filter[key] = `${value}`; + const isValidNumber = /^-?\d+(\.\d+)?(?!.)/.test(value); + const isValidEventID = /^\d+\.\d+-[a-zA-Z0-9]+$/.test(value); + + if ( + value != "true" && + value != "false" && + !isValidNumber && + !isValidEventID + ) { + filter[key] = value.includes(",") ? value.split(",") : [value]; + } else { + if (value != undefined) { + try { + filter[key] = JSON.parse(value); + } catch { + filter[key] = `${value}`; + } } } } }); return filter as F; - }, [rawParams]); + }, [rawParams, arrayKeys]); const searchParams = useMemo(() => { if (filter == undefined || Object.keys(filter).length == 0) { diff --git a/web/src/pages/Explore.tsx b/web/src/pages/Explore.tsx index 62d55fee9..9cb97ae2a 100644 --- a/web/src/pages/Explore.tsx +++ b/web/src/pages/Explore.tsx @@ -58,7 +58,13 @@ export default function Explore() { const [search, setSearch] = useState(""); const [searchFilter, setSearchFilter, searchSearchParams] = - useApiFilterArgs(); + useApiFilterArgs([ + "cameras", + "labels", + "sub_labels", + "recognized_license_plate", + "zones", + ]); const searchTerm = useMemo( () => searchSearchParams?.["query"] || "", diff --git a/web/src/views/settings/NotificationsSettingsView.tsx b/web/src/views/settings/NotificationsSettingsView.tsx index 410ba9742..36213fc0e 100644 --- a/web/src/views/settings/NotificationsSettingsView.tsx +++ b/web/src/views/settings/NotificationsSettingsView.tsx @@ -523,7 +523,9 @@ export default function NotificationView({ aria-label={t("notification.registerDevice")} disabled={ (!config?.notifications.enabled && - notificationCameras.length === 0) || + notificationCameras.length === 0 && + !form.watch("allEnabled") && + form.watch("cameras").length === 0) || publicKey == undefined } onClick={() => {