Move overrides to a single configuration section.

This commit is contained in:
Dermot Duffy
2022-01-14 21:31:16 -08:00
parent 55ca108a9b
commit ee9f22f9f7
4 changed files with 82 additions and 44 deletions
+26 -15
View File
@@ -1,5 +1,6 @@
import type { import type {
FrigateCardCondition, FrigateCardCondition,
OverrideConfigurationKey,
RawFrigateCardConfig, RawFrigateCardConfig,
} from './types'; } from './types';
import { merge, cloneDeep } from 'lodash-es'; import { merge, cloneDeep } from 'lodash-es';
@@ -27,7 +28,8 @@ export function evaluateCondition(
result &&= !!state.view && condition.view.includes(state.view); result &&= !!state.view && condition.view.includes(state.view);
} }
if (condition?.fullscreen !== undefined) { if (condition?.fullscreen !== undefined) {
result &&= state.fullscreen !== undefined && condition.fullscreen == state.fullscreen; result &&=
state.fullscreen !== undefined && condition.fullscreen == state.fullscreen;
} }
if (condition?.camera?.length) { if (condition?.camera?.length) {
result &&= !!state.camera && condition.camera.includes(state.camera); result &&= !!state.camera && condition.camera.includes(state.camera);
@@ -78,32 +80,41 @@ export function conditionStateRequestHandler(
ev.conditionState = conditionState; ev.conditionState = conditionState;
} }
type Overrides = { type RawOverrides = {
conditions: FrigateCardCondition; conditions: FrigateCardCondition;
overrides: RawFrigateCardConfig; overrides: RawFrigateCardConfig;
}[]; }[];
export function getOverriddenConfig( export function getOverriddenConfig(
config: Readonly<RawFrigateCardConfig>, config: Readonly<RawFrigateCardConfig>,
overrides: Readonly<RawOverrides> | undefined,
conditionState?: Readonly<ConditionState>, conditionState?: Readonly<ConditionState>,
overrides?: Readonly<Overrides>,
): RawFrigateCardConfig { ): RawFrigateCardConfig {
const overridesSource =
overrides || (config['overrides'] as Readonly<Overrides> | undefined);
if (!overridesSource) {
return config;
}
const output = cloneDeep(config); const output = cloneDeep(config);
let overridden = false; let overridden = false;
if (overrides) {
for (const override of overridesSource) { for (const override of overrides) {
if (evaluateCondition(override.conditions, conditionState)) { if (evaluateCondition(override.conditions, conditionState)) {
merge(output, override.overrides); merge(output, override.overrides);
overridden = true; overridden = true;
}
} }
} }
// Attempt to return the same configuration object if it has not been // Attempt to return the same configuration object if it has not been
// overridden (to reduce re-renders for a configuration that has not changed). // overridden (to reduce re-renders for a configuration that has not changed).
return overridden ? output : config; return overridden ? output : config;
} }
export function getOverridesByKey(
overrides: Readonly<RawOverrides> | undefined,
key: OverrideConfigurationKey,
): RawOverrides {
return (
overrides
?.filter((o) => key in o.overrides)
.map((o) => ({
conditions: o.conditions,
overrides: o.overrides[key] as RawFrigateCardConfig,
})) ?? []
);
}
+14 -9
View File
@@ -26,7 +26,6 @@ import {
ActionType, ActionType,
CameraConfig, CameraConfig,
GetFrigateCardMenuButtonParameters, GetFrigateCardMenuButtonParameters,
LiveConfig,
RawFrigateCardConfig, RawFrigateCardConfig,
entitySchema, entitySchema,
frigateCardConfigSchema, frigateCardConfigSchema,
@@ -79,6 +78,7 @@ import {
ConditionState, ConditionState,
conditionStateRequestHandler, conditionStateRequestHandler,
getOverriddenConfig, getOverriddenConfig,
getOverridesByKey,
} from './card-condition.js'; } from './card-condition.js';
/** A note on media callbacks: /** A note on media callbacks:
@@ -135,6 +135,9 @@ export class FrigateCard extends LitElement {
@state() @state()
public config!: FrigateCardConfig; public config!: FrigateCardConfig;
@state()
public _overriddenConfig?: FrigateCardConfig;
protected _interactionTimerID: number | null = null; protected _interactionTimerID: number | null = null;
@property({ attribute: false }) @property({ attribute: false })
@@ -226,6 +229,11 @@ export class FrigateCard extends LitElement {
fullscreen: screenfull.isEnabled && screenfull.isFullscreen, fullscreen: screenfull.isEnabled && screenfull.isFullscreen,
camera: this._view?.camera, camera: this._view?.camera,
}; };
this._overriddenConfig = getOverriddenConfig(
this.config,
this.config.overrides,
this._conditionState) as FrigateCardConfig;
} }
/** /**
@@ -1040,17 +1048,13 @@ export class FrigateCard extends LitElement {
let specificActions: Actions | undefined = undefined; let specificActions: Actions | undefined = undefined;
if (this._view?.is('live')) { if (this._view?.is('live')) {
const config = getOverriddenConfig( specificActions = this._overriddenConfig?.live.actions;
this.config.live,
this._conditionState,
) as LiveConfig;
specificActions = config.actions;
} else if (this._view?.isGalleryView()) { } else if (this._view?.isGalleryView()) {
specificActions = this.config.event_gallery?.actions; specificActions = this._overriddenConfig?.event_gallery?.actions;
} else if (this._view?.isViewerView()) { } else if (this._view?.isViewerView()) {
specificActions = this.config.event_viewer.actions; specificActions = this._overriddenConfig?.event_viewer.actions;
} else if (this._view?.is('image')) { } else if (this._view?.is('image')) {
specificActions = this.config.image?.actions; specificActions = this._overriddenConfig?.image?.actions;
} }
return { ...this.config.view.actions, ...specificActions }; return { ...this.config.view.actions, ...specificActions };
} }
@@ -1208,6 +1212,7 @@ export class FrigateCard extends LitElement {
.view=${this._view} .view=${this._view}
.liveConfig=${this.config.live} .liveConfig=${this.config.live}
.conditionState=${this._conditionState} .conditionState=${this._conditionState}
.liveOverrides=${getOverridesByKey(this.config.overrides, 'live')}
.cameras=${this._cameras} .cameras=${this._cameras}
.preload=${this.config.live.preload && !this._view.is('live')} .preload=${this.config.live.preload && !this._view.is('live')}
class="${classMap(liveClasses)}" class="${classMap(liveClasses)}"
+14 -1
View File
@@ -24,6 +24,7 @@ import {
MediaShowInfo, MediaShowInfo,
WebRTCConfig, WebRTCConfig,
FrigateCardError, FrigateCardError,
LiveOverrides,
} from '../types.js'; } from '../types.js';
import { EmblaOptionsType } from 'embla-carousel'; import { EmblaOptionsType } from 'embla-carousel';
import { HomeAssistant } from 'custom-card-helpers'; import { HomeAssistant } from 'custom-card-helpers';
@@ -79,6 +80,9 @@ export class FrigateCardLive extends LitElement {
@property({ attribute: false }) @property({ attribute: false })
protected liveConfig?: LiveConfig; protected liveConfig?: LiveConfig;
@property({ attribute: false })
protected liveOverrides?: LiveOverrides;
@property({ attribute: false }) @property({ attribute: false })
protected conditionState?: ConditionState; protected conditionState?: ConditionState;
@@ -177,6 +181,7 @@ export class FrigateCardLive extends LitElement {
const config = getOverriddenConfig( const config = getOverriddenConfig(
this.liveConfig, this.liveConfig,
this.liveOverrides,
this.conditionState, this.conditionState,
) as LiveConfig; ) as LiveConfig;
@@ -192,6 +197,7 @@ export class FrigateCardLive extends LitElement {
.liveConfig=${this.liveConfig} .liveConfig=${this.liveConfig}
.preload=${this._preload} .preload=${this._preload}
.conditionState=${this.conditionState} .conditionState=${this.conditionState}
.liveOverrides=${this.liveOverrides}
@frigate-card:media-show=${this._mediaShowHandler} @frigate-card:media-show=${this._mediaShowHandler}
@frigate-card:carousel:select=${() => { @frigate-card:carousel:select=${() => {
// Re-rendering the component will cause the thumbnails to be // Re-rendering the component will cause the thumbnails to be
@@ -226,6 +232,9 @@ export class FrigateCardLiveCarousel extends FrigateCardMediaCarousel {
@property({ attribute: false }) @property({ attribute: false })
protected liveConfig?: LiveConfig; protected liveConfig?: LiveConfig;
@property({ attribute: false })
protected liveOverrides?: LiveOverrides;
@property({ attribute: false }) @property({ attribute: false })
protected preload?: boolean; protected preload?: boolean;
@@ -366,7 +375,10 @@ export class FrigateCardLiveCarousel extends FrigateCardMediaCarousel {
camera: camera, camera: camera,
}); });
const config = getOverriddenConfig(this.liveConfig, conditionState) as LiveConfig; const config = getOverriddenConfig(
this.liveConfig,
this.liveOverrides,
conditionState) as LiveConfig;
return html` <div class="embla__slide"> return html` <div class="embla__slide">
<frigate-card-live-provider <frigate-card-live-provider
@@ -441,6 +453,7 @@ export class FrigateCardLiveCarousel extends FrigateCardMediaCarousel {
const config = getOverriddenConfig( const config = getOverriddenConfig(
this.liveConfig, this.liveConfig,
this.liveOverrides,
this.conditionState, this.conditionState,
) as LiveConfig; ) as LiveConfig;
+28 -19
View File
@@ -379,18 +379,6 @@ export type PictureElement = z.infer<typeof pictureElementSchema>;
const pictureElementsSchema = pictureElementSchema.array().optional(); const pictureElementsSchema = pictureElementSchema.array().optional();
export type PictureElements = z.infer<typeof pictureElementsSchema>; export type PictureElements = z.infer<typeof pictureElementsSchema>;
/**
* Configuration overrides
*/
const overridesSchema = z
.object({
conditions: frigateCardConditionSchema,
overrides: z.record(z.unknown()),
})
.array()
.optional();
export type Overrides = z.infer<typeof overridesSchema>;
/** /**
* View configuration section. * View configuration section.
*/ */
@@ -562,13 +550,6 @@ const liveConfigSchema = liveOverridableConfigSchema
preload: z.boolean().default(liveConfigDefault.preload), preload: z.boolean().default(liveConfigDefault.preload),
lazy_load: z.boolean().default(liveConfigDefault.lazy_load), lazy_load: z.boolean().default(liveConfigDefault.lazy_load),
draggable: z.boolean().default(liveConfigDefault.draggable), draggable: z.boolean().default(liveConfigDefault.draggable),
overrides: z
.object({
conditions: frigateCardConditionSchema,
overrides: liveOverridableConfigSchema,
})
.array()
.optional(),
}) })
.default(liveConfigDefault); .default(liveConfigDefault);
export type LiveConfig = z.infer<typeof liveConfigSchema>; export type LiveConfig = z.infer<typeof liveConfigSchema>;
@@ -702,6 +683,31 @@ const dimensionsConfigSchema = z
}) })
.default(dimensionsConfigDefault); .default(dimensionsConfigDefault);
/**
* Configuration overrides
*/
const overrideConfigurationSchema = z.object({
live: liveOverridableConfigSchema.optional(),
});
export type OverrideConfigurationKey = keyof z.infer<typeof overrideConfigurationSchema>;
const overridesSchema = z
.object({
conditions: frigateCardConditionSchema,
overrides: overrideConfigurationSchema,
})
.array()
.optional();
const liveOverridesSchema = z
.object({
conditions: frigateCardConditionSchema,
overrides: liveOverridableConfigSchema,
})
.array()
.optional();
export type LiveOverrides = z.infer<typeof liveOverridesSchema>;
/** /**
* Main card config. * Main card config.
*/ */
@@ -717,6 +723,9 @@ export const frigateCardConfigSchema = z.object({
elements: pictureElementsSchema, elements: pictureElementsSchema,
dimensions: dimensionsConfigSchema, dimensions: dimensionsConfigSchema,
// Configuration overrides.
overrides: overridesSchema,
// Stock lovelace card config. // Stock lovelace card config.
type: z.string(), type: z.string(),
test_gui: z.boolean().optional(), test_gui: z.boolean().optional(),