Miscellaneous fixes (#23201)

* sync filter entries with track and listen labels

- Auto-populate `audio.filters` from `audio.listen` instead of the full audio labelmap, matching how `objects.filters` is keyed by `track` (no longer need to populate the full audio labelmap, which was added in #22630)
- Synthesize the matching filter entries in the settings form on load so each track/listen label shows its collapsible after a profile is selected, since the backend's auto-populate only runs at config init

* translate main label for lifecycle description with attribute

* reject restricted go2rtc stream sources when added via api

* add env var check function
This commit is contained in:
Josh Hawkins
2026-05-15 10:06:38 -05:00
committed by GitHub
parent d9c1ea908d
commit c6eadfebb8
9 changed files with 135 additions and 69 deletions
@@ -22,7 +22,7 @@ import {
modifySchemaForSection,
getEffectiveDefaultsForSection,
sanitizeOverridesForSection,
synthesizeMissingObjectFilters,
synthesizeMissingFilters,
} from "./section-special-cases";
import { getSectionValidation } from "../section-validations";
import { useConfigOverride } from "@/hooks/use-config-override";
@@ -370,7 +370,7 @@ export function ConfigSection({
return {};
}
return synthesizeMissingObjectFilters(
return synthesizeMissingFilters(
sectionPath,
rawSectionValue,
modifiedSchema ?? undefined,
@@ -128,22 +128,31 @@ export function getEffectiveDefaultsForSection(
return schemaDefaults;
}
// Sections whose `filters` dict is keyed by a sibling list field. The backend
// auto-populates these filters at config init but doesn't re-run after profile
// merges, so we synthesize the missing entries on the frontend.
const FILTER_SECTIONS: Record<string, { listField: string }> = {
objects: { listField: "track" },
audio: { listField: "listen" },
};
/**
* Add default filter entries for any label in `objects.track` that isn't
* already in `objects.filters`, so each tracked label gets a collapsible.
* The backend only auto-populates filters at config init, not after profile
* merges.
* Add default filter entries for any label in the section's list field
* (e.g. `objects.track`, `audio.listen`) that isn't already in `filters`, so
* each label gets a collapsible. The backend only auto-populates filters at
* config init, not after profile merges.
*/
export function synthesizeMissingObjectFilters(
export function synthesizeMissingFilters(
sectionPath: string,
data: unknown,
sectionSchema: RJSFSchema | undefined,
): unknown {
if (sectionPath !== "objects") return data;
const sectionConfig = FILTER_SECTIONS[sectionPath];
if (!sectionConfig) return data;
if (!isJsonObject(data)) return data;
const trackValue = (data as JsonObject).track;
if (!Array.isArray(trackValue) || trackValue.length === 0) return data;
const listValue = (data as JsonObject)[sectionConfig.listField];
if (!Array.isArray(listValue) || listValue.length === 0) return data;
const properties = (sectionSchema as { properties?: Record<string, unknown> })
?.properties;
@@ -160,7 +169,7 @@ export function synthesizeMissingObjectFilters(
const newFilters: JsonObject = { ...existingFilters };
let added = false;
for (const label of trackValue) {
for (const label of listValue) {
if (typeof label !== "string") continue;
if (Object.prototype.hasOwnProperty.call(newFilters, label)) continue;
newFilters[label] = (