diff --git a/src/card.ts b/src/card.ts index ad7b0a74..53024f8c 100644 --- a/src/card.ts +++ b/src/card.ts @@ -354,7 +354,7 @@ export class FrigateCard extends LitElement { } const cameraConfig = this._getSelectedCameraConfig(); - if (this.config.menu.buttons.frigate_ui && cameraConfig && cameraConfig.url) { + if (this.config.menu.buttons.frigate_ui && cameraConfig && cameraConfig.frigate_url) { buttons.push( this._getFrigateCardMenuButton({ tap_action: 'frigate_ui', @@ -808,13 +808,13 @@ export class FrigateCard extends LitElement { */ protected _getFrigateURLFromContext(): string | null { const cameraConfig = this._getSelectedCameraConfig(); - if (!cameraConfig || !cameraConfig.url || !this._view) { + if (!cameraConfig || !cameraConfig.frigate_url || !this._view) { return null; } if (this._view.isViewerView() || this._view.isGalleryView()) { - return `${cameraConfig.url}/events?camera=${cameraConfig.camera_name}`; + return `${cameraConfig.frigate_url}/events?camera=${cameraConfig.camera_name}`; } - return `${cameraConfig.url}/cameras/${cameraConfig.camera_name}`; + return `${cameraConfig.frigate_url}/cameras/${cameraConfig.camera_name}`; } /** diff --git a/src/components/live.ts b/src/components/live.ts index 13309306..98cc2bc6 100644 --- a/src/components/live.ts +++ b/src/components/live.ts @@ -1,6 +1,5 @@ // TODO webrtc entities in camera section? // TODO conditional elements based on camera name (requires event changed to propagate upwards) -// TODO change url to frigate_url? Would need to also fix upgrade logic to refer to new name. // TODO Remove media load event warning // TODO readme // TODO search for TODOs diff --git a/src/config-mgmt.ts b/src/config-mgmt.ts index adbbb9f1..1341803f 100644 --- a/src/config-mgmt.ts +++ b/src/config-mgmt.ts @@ -163,6 +163,16 @@ export const moveConfigValue = ( return false; }; +/** + * Given an array path, return a true path. + * @param path The array path (should have a '#'). + * @param index The numeric array index to use. + * @returns The true config path. + */ +export const getArrayConfigPath = (path: string, index: number): string => { + return path.replace('#', index.toString()); +}; + /** * Upgrade by moving a property from one location to another. * @param oldPath The old property path. @@ -185,15 +195,17 @@ const upgradeMoveTo = function ( * @param key A string key. * @returns A safe key. */ -// const sanitizeKeySegment = (key: string): string => { -// return key.replace(/\.+/g, '_'); -// } - const upgradeToMultipleCameras = (): ((obj: RawFrigateCardConfig) => boolean) => { return function (obj: RawFrigateCardConfig): boolean { let modified = false; - const camera = {} + let cameras = getConfigValue(obj, CONF_CAMERAS) as RawFrigateCardConfigArray; + if (!Array.isArray(cameras)) { + // Note: This will replace `cameras` if it already exists and isn't an + // array. + cameras = [] + } + const imports = { 'camera_entity': CONF_CAMERAS_ARRAY_CAMERA_ENTITY, 'frigate.camera_name': CONF_CAMERAS_ARRAY_CAMERA_NAME, @@ -202,26 +214,15 @@ const upgradeToMultipleCameras = (): ((obj: RawFrigateCardConfig) => boolean) => 'frigate.url': CONF_CAMERAS_ARRAY_URL, 'frigate.zone': CONF_CAMERAS_ARRAY_ZONE, } + const cameraIndex = cameras.length; Object.keys(imports).forEach((key) => { const oldValue = getConfigValue(obj, key); if (oldValue !== undefined) { - camera[imports[key]] = oldValue; deleteConfigValue(obj, key) + setConfigValue(obj, getArrayConfigPath(imports[key], cameraIndex), oldValue); modified = true; } }) - - if (modified) { - let cameras = getConfigValue(obj, CONF_CAMERAS) as RawFrigateCardConfigArray; - if (!Array.isArray(cameras)) { - // Note: This will replace `cameras` if it already exists and isn't an - // array. - cameras = [] - } - cameras.push(camera); - setConfigValue(obj, CONF_CAMERAS, cameras) - trimConfig(obj); - } return modified; } } diff --git a/src/const.ts b/src/const.ts index bd5eeca9..c1d2af94 100644 --- a/src/const.ts +++ b/src/const.ts @@ -7,7 +7,7 @@ export const CONF_CAMERAS_ARRAY_CAMERA_ENTITY = 'cameras.#.camera_entity'; export const CONF_CAMERAS_ARRAY_CAMERA_NAME = 'cameras.#.camera_name'; export const CONF_CAMERAS_ARRAY_CLIENT_ID = 'cameras.#.client_id'; export const CONF_CAMERAS_ARRAY_LABEL = 'cameras.#.label'; -export const CONF_CAMERAS_ARRAY_URL = 'cameras.#.url'; +export const CONF_CAMERAS_ARRAY_URL = 'cameras.#.frigate_url'; export const CONF_CAMERAS_ARRAY_ZONE = 'cameras.#.zone'; export const CONF_CAMERAS_ARRAY_ID = 'cameras.#.id'; diff --git a/src/editor.ts b/src/editor.ts index 336f0415..715fda41 100644 --- a/src/editor.ts +++ b/src/editor.ts @@ -55,6 +55,7 @@ import { arrayMove, getEntityTitle, prettifyFrigateName } from './common.js'; import { copyConfig, deleteConfigValue, + getArrayConfigPath, getConfigValue, isConfigUpgradeable, setConfigValue, @@ -320,11 +321,6 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor cameraEntities: string[], addNewCamera?: boolean, ): TemplateResult | void { - // Get the config path for this camera (taking into account its camera index). - const getArrayPath = (path: string): string => { - return path.replace('#', cameraIndex.toString()); - }; - // Make a new config and update the editor with changes on it, const modifyConfig = (func: (config: RawFrigateCardConfig) => boolean): void => { if (this._config) { @@ -348,7 +344,8 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor !Array.isArray(this._config.cameras) || cameraIndex <= 0} @click=${() => - !addNewCamera && modifyConfig((config: RawFrigateCardConfig): boolean => { + !addNewCamera && + modifyConfig((config: RawFrigateCardConfig): boolean => { if (Array.isArray(config.cameras) && cameraIndex > 0) { arrayMove(config.cameras, cameraIndex, cameraIndex - 1); this._expandedCameraIndex = cameraIndex - 1; @@ -367,7 +364,8 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor !Array.isArray(this._config.cameras) || cameraIndex >= this._config.cameras.length - 1} @click=${() => - !addNewCamera && modifyConfig((config: RawFrigateCardConfig): boolean => { + !addNewCamera && + modifyConfig((config: RawFrigateCardConfig): boolean => { if ( Array.isArray(config.cameras) && cameraIndex < config.cameras.length - 1 @@ -400,15 +398,27 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor ${this._renderDropdown( - getArrayPath(CONF_CAMERAS_ARRAY_CAMERA_ENTITY), + getArrayConfigPath(CONF_CAMERAS_ARRAY_CAMERA_ENTITY, cameraIndex), cameraEntities, )} - ${this._renderStringInput(getArrayPath(CONF_CAMERAS_ARRAY_CAMERA_NAME))} - ${this._renderStringInput(getArrayPath(CONF_CAMERAS_ARRAY_URL))} - ${this._renderStringInput(getArrayPath(CONF_CAMERAS_ARRAY_LABEL))} - ${this._renderStringInput(getArrayPath(CONF_CAMERAS_ARRAY_ZONE))} - ${this._renderStringInput(getArrayPath(CONF_CAMERAS_ARRAY_CLIENT_ID))} - ${this._renderStringInput(getArrayPath(CONF_CAMERAS_ARRAY_ID))} + ${this._renderStringInput( + getArrayConfigPath(CONF_CAMERAS_ARRAY_CAMERA_NAME, cameraIndex), + )} + ${this._renderStringInput( + getArrayConfigPath(CONF_CAMERAS_ARRAY_URL, cameraIndex), + )} + ${this._renderStringInput( + getArrayConfigPath(CONF_CAMERAS_ARRAY_LABEL, cameraIndex), + )} + ${this._renderStringInput( + getArrayConfigPath(CONF_CAMERAS_ARRAY_ZONE, cameraIndex), + )} + ${this._renderStringInput( + getArrayConfigPath(CONF_CAMERAS_ARRAY_CLIENT_ID, cameraIndex), + )} + ${this._renderStringInput( + getArrayConfigPath(CONF_CAMERAS_ARRAY_ID, cameraIndex), + )} ` : ``} `; diff --git a/src/localize/languages/en.json b/src/localize/languages/en.json index 670c9136..e6574f03 100644 --- a/src/localize/languages/en.json +++ b/src/localize/languages/en.json @@ -15,7 +15,7 @@ "client_id": "Frigate client id (For >1 Frigate server)", "id": "Unique id for this camera in this card", "label": "Frigate label/object filter", - "url": "Frigate server URL", + "frigate_url": "Frigate server URL", "zone": "Frigate zone" }, "view": { diff --git a/src/types.ts b/src/types.ts index 562328c8..5ab82a2f 100644 --- a/src/types.ts +++ b/src/types.ts @@ -356,8 +356,8 @@ export const cameraConfigDefault = { }; const cameraConfigDefaultSchema = z .object({ - // No URL validation to allow relative URLs within HA (e.g. addons). - url: z.string().optional(), + // No URL validation to allow relative URLs within HA (e.g. Frigate addon). + frigate_url: z.string().optional(), client_id: z.string().optional().default(cameraConfigDefault.client_id), camera_name: z.string().optional(), label: z.string().optional(),