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