diff --git a/src/components/live.ts b/src/components/live.ts index cdeb07ea..6d557270 100644 --- a/src/components/live.ts +++ b/src/components/live.ts @@ -1,4 +1,7 @@ // TODO autodetect live provider from cameras configuration, or allow explicit setting. +// TODO config-mgmt move for live provider +// TODO unroll webrtc object in camera config for parity with live provider? +// TODO order of cameras may not be being preserved. // TODO verify README links worked correctly (e.g. basic cameras configuration) import { @@ -506,7 +509,7 @@ export class FrigateCardLiveProvider extends LitElement { public disabled = false; protected _getResolvedProvider(): LiveProvider { - if (this.liveConfig?.provider === 'auto') { + if (this.cameraConfig?.live_provider === 'auto') { if (this.cameraConfig?.webrtc?.entity || this.cameraConfig?.webrtc?.url) { return 'webrtc'; } else if (this.cameraConfig?.camera_entity) { @@ -514,9 +517,9 @@ export class FrigateCardLiveProvider extends LitElement { } else if (this.cameraConfig?.camera_name) { return 'frigate-jsmpeg'; } - return frigateCardConfigDefaults.live.provider; + return frigateCardConfigDefaults.cameras.live_provider; } - return this.liveConfig?.provider || frigateCardConfigDefaults.live.provider; + return this.cameraConfig?.live_provider || frigateCardConfigDefaults.cameras.live_provider; } /** diff --git a/src/config-mgmt.ts b/src/config-mgmt.ts index 672498e7..a80b9e1b 100644 --- a/src/config-mgmt.ts +++ b/src/config-mgmt.ts @@ -5,6 +5,7 @@ import { CONF_CAMERAS_ARRAY_CAMERA_NAME, CONF_CAMERAS_ARRAY_CLIENT_ID, CONF_CAMERAS_ARRAY_LABEL, + CONF_CAMERAS_ARRAY_LIVE_PROVIDER, CONF_CAMERAS_ARRAY_URL, CONF_CAMERAS_ARRAY_WEBRTC_ENTITY, CONF_CAMERAS_ARRAY_WEBRTC_URL, @@ -14,7 +15,6 @@ import { CONF_EVENT_VIEWER_CONTROLS_NEXT_PREVIOUS_STYLE, CONF_IMAGE_SRC, CONF_LIVE_PRELOAD, - CONF_LIVE_PROVIDER, CONF_MENU, CONF_MENU_BUTTON_SIZE, CONF_MENU_MODE, @@ -37,7 +37,7 @@ export const setConfigValue = ( keys: string | (string | number)[], value: unknown, ): void => { - set(obj, keys, value) + set(obj, keys, value); }; /** @@ -213,13 +213,11 @@ const upgradeToMultipleCameras = (): ((obj: RawFrigateCardConfig) => boolean) => 'frigate.zone': CONF_CAMERAS_ARRAY_ZONE, 'live.webrtc.entity': CONF_CAMERAS_ARRAY_WEBRTC_ENTITY, 'live.webrtc.url': CONF_CAMERAS_ARRAY_WEBRTC_URL, + 'live.provider': CONF_CAMERAS_ARRAY_LIVE_PROVIDER, }; Object.keys(imports).forEach((key) => { - modified = moveConfigValue( - obj, - key, - getArrayConfigPath(imports[key], 0), - ) || modified; + modified = + moveConfigValue(obj, key, getArrayConfigPath(imports[key], 0)) || modified; }); return modified; }; @@ -231,27 +229,29 @@ const upgradeToMultipleCameras = (): ((obj: RawFrigateCardConfig) => boolean) => * @param key A string key. * @returns A safe key. */ - const updateMenuConditionToMenuOverride = (): ((obj: RawFrigateCardConfig) => boolean) => { +const updateMenuConditionToMenuOverride = (): (( + obj: RawFrigateCardConfig, +) => boolean) => { return function (obj: RawFrigateCardConfig): boolean { - const menuConditions = getConfigValue(obj, `${CONF_MENU}.conditions`) as RawFrigateCardConfig; + const menuConditions = getConfigValue( + obj, + `${CONF_MENU}.conditions`, + ) as RawFrigateCardConfig; if (menuConditions === undefined) { return false; } - const overrides = getConfigValue(obj, `${CONF_OVERRIDES}`) as RawFrigateCardConfigArray || []; - setConfigValue( - obj, - `${CONF_OVERRIDES}.[${overrides.length}]`, - { - conditions: menuConditions, - overrides: { - menu: { - mode: 'none' - } - } - } - ); + const overrides = + (getConfigValue(obj, `${CONF_OVERRIDES}`) as RawFrigateCardConfigArray) || []; + setConfigValue(obj, `${CONF_OVERRIDES}.[${overrides.length}]`, { + conditions: menuConditions, + overrides: { + menu: { + mode: 'none', + }, + }, + }); deleteConfigValue(obj, `${CONF_MENU}.conditions`); return true; }; @@ -266,7 +266,7 @@ const UPGRADES = [ upgradeMoveTo('zone', 'frigate.zone'), upgradeMoveTo('view_default', CONF_VIEW_DEFAULT), upgradeMoveTo('view_timeout', CONF_VIEW_TIMEOUT), - upgradeMoveTo('live_provider', CONF_LIVE_PROVIDER), + upgradeMoveTo('live_provider', 'live.provider'), upgradeMoveTo('live_preload', CONF_LIVE_PRELOAD), upgradeMoveTo('webrtc', 'live.webrtc'), upgradeMoveTo('autoplay_clip', CONF_EVENT_VIEWER_AUTOPLAY_CLIP), diff --git a/src/const.ts b/src/const.ts index 1c53b912..a270cc8e 100644 --- a/src/const.ts +++ b/src/const.ts @@ -16,6 +16,7 @@ export const CONF_CAMERAS_ARRAY_ICON = `${CONF_CAMERAS}.#.icon` as const; export const CONF_CAMERAS_ARRAY_WEBRTC_ENTITY = `${CONF_CAMERAS}.#.webrtc.entity` as const; export const CONF_CAMERAS_ARRAY_WEBRTC_URL = `${CONF_CAMERAS}.#.webrtc.url` as const; +export const CONF_CAMERAS_ARRAY_LIVE_PROVIDER = `${CONF_CAMERAS}.#.live_provider` as const; export const CONF_VIEW = 'view' as const; export const CONF_VIEW_DEFAULT = `${CONF_VIEW}.default` as const; @@ -52,7 +53,6 @@ export const CONF_LIVE_DRAGGABLE = `${CONF_LIVE}.draggable` as const; export const CONF_LIVE_JSMPEG = `${CONF_LIVE}.jsmpeg` as const; export const CONF_LIVE_LAZY_LOAD = `${CONF_LIVE}.lazy_load` as const; export const CONF_LIVE_PRELOAD = `${CONF_LIVE}.preload` as const; -export const CONF_LIVE_PROVIDER = `${CONF_LIVE}.provider` as const; export const CONF_LIVE_WEBRTC = `${CONF_LIVE}.webrtc` as const; export const CONF_LIVE_WEBRTC_ENTITY = `${CONF_LIVE_WEBRTC}.entity` as const; export const CONF_LIVE_WEBRTC_URL = `${CONF_LIVE_WEBRTC}.url` as const; diff --git a/src/editor.ts b/src/editor.ts index 93083a4c..63c0d2a8 100644 --- a/src/editor.ts +++ b/src/editor.ts @@ -19,6 +19,7 @@ import { CONF_CAMERAS_ARRAY_ICON, CONF_CAMERAS_ARRAY_ID, CONF_CAMERAS_ARRAY_LABEL, + CONF_CAMERAS_ARRAY_LIVE_PROVIDER, CONF_CAMERAS_ARRAY_TITLE, CONF_CAMERAS_ARRAY_URL, CONF_CAMERAS_ARRAY_WEBRTC_ENTITY, @@ -42,7 +43,6 @@ import { CONF_LIVE_DRAGGABLE, CONF_LIVE_LAZY_LOAD, CONF_LIVE_PRELOAD, - CONF_LIVE_PROVIDER, CONF_MENU_BUTTONS_CLIPS, CONF_MENU_BUTTONS_FRIGATE, CONF_MENU_BUTTONS_FRIGATE_DOWNLOAD, @@ -322,6 +322,14 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor cameraEntities: string[], addNewCamera?: boolean, ): TemplateResult | void { + const liveProviders = { + '': '', + auto: localize('config.cameras.live_providers.auto'), + frigate: localize('config.cameras.live_providers.frigate'), + 'frigate-jsmpeg': localize('config.cameras.live_providers.frigate-jsmpeg'), + webrtc: localize('config.cameras.live_providers.webrtc'), + } as const; + // Make a new config and update the editor with changes on it, const modifyConfig = (func: (config: RawFrigateCardConfig) => boolean): void => { if (this._config) { @@ -405,6 +413,9 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor ${this._renderStringInput( getArrayConfigPath(CONF_CAMERAS_ARRAY_CAMERA_NAME, cameraIndex), )} + ${this._renderDropdown( + getArrayConfigPath(CONF_CAMERAS_ARRAY_LIVE_PROVIDER, cameraIndex), + liveProviders)} ${this._renderStringInput( getArrayConfigPath(CONF_CAMERAS_ARRAY_URL, cameraIndex), )} @@ -530,14 +541,6 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor below: localize('config.menu.modes.below'), }; - const liveProviders = { - '': '', - auto: localize('config.live.providers.auto'), - frigate: localize('config.live.providers.frigate'), - 'frigate-jsmpeg': localize('config.live.providers.frigate-jsmpeg'), - webrtc: localize('config.live.providers.webrtc'), - }; - const eventViewerNextPreviousControlStyles = { '': '', thumbnails: localize( @@ -685,7 +688,6 @@ export class FrigateCardEditor extends LitElement implements LovelaceCardEditor CONF_LIVE_LAZY_LOAD, defaults.live.lazy_load, )} - ${this._renderDropdown(CONF_LIVE_PROVIDER, liveProviders)} ${this._renderDropdown( CONF_LIVE_CONTROLS_NEXT_PREVIOUS_STYLE, liveNextPreviousControlStyles, diff --git a/src/localize/languages/en.json b/src/localize/languages/en.json index f0aeaefc..35eec787 100644 --- a/src/localize/languages/en.json +++ b/src/localize/languages/en.json @@ -18,11 +18,18 @@ "frigate_url": "Frigate server URL", "title": "Title for this camera (Autodetected from entity)", "icon": "Icon for this camera (Autodetected from entity)", - "zone": "Frigate zone", + "live_provider": "Live view provider for this camera", + "live_providers": { + "auto": "Automatic", + "frigate": "Frigate", + "frigate-jsmpeg": "Frigate JSMpeg", + "webrtc": "WebRTC" + }, "webrtc": { "entity": "WebRTC Camera Entity (Not a Frigate camera)", "url": "WebRTC Camera URL" - } + }, + "zone": "Frigate zone" }, "view": { "default": "Default view", @@ -64,13 +71,6 @@ }, "live": { "preload": "Preload live view in the background", - "provider": "Live view provider", - "providers": { - "auto": "Automatic", - "frigate": "Frigate", - "frigate-jsmpeg": "Frigate JSMpeg", - "webrtc": "WebRTC" - }, "draggable": "Live cameras view can be dragged/swiped", "lazy_load": "Live cameras are lazily loaded in carousel", "controls": { diff --git a/src/types.ts b/src/types.ts index 62a6b4f2..7730e493 100644 --- a/src/types.ts +++ b/src/types.ts @@ -282,6 +282,7 @@ const customSchema = z */ export const cameraConfigDefault = { client_id: 'frigate' as const, + live_provider: 'auto' as const, }; const webrtcCameraConfigSchema = z.object({ entity: z.string().optional(), @@ -291,11 +292,12 @@ const cameraConfigSchema = z .object({ // 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), + client_id: z.string().default(cameraConfigDefault.client_id), camera_name: z.string().optional(), label: z.string().optional(), zone: z.string().optional(), camera_entity: z.string().optional(), + live_provider: z.enum(LIVE_PROVIDERS).default(cameraConfigDefault.live_provider), // Used for presentation in the UI (autodetected from the entity if // specified). @@ -446,7 +448,6 @@ export type NextPreviousControlConfig = z.infer