Move overrides to a single configuration section.
This commit is contained in:
+22
-11
@@ -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
@@ -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
@@ -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
@@ -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(),
|
||||||
|
|||||||
Reference in New Issue
Block a user