Use less fancy camera condition matching.

This commit is contained in:
Dermot Duffy
2022-01-14 21:31:16 -08:00
parent a15ea2af45
commit 55ca108a9b
4 changed files with 17 additions and 49 deletions
+8 -38
View File
@@ -1,16 +1,13 @@
import type { import type {
CameraConfig,
FrigateCardCondition, FrigateCardCondition,
RawFrigateCardConfig, RawFrigateCardConfig,
} from './types'; } from './types';
import { merge, cloneDeep } from 'lodash-es'; import { merge, cloneDeep } from 'lodash-es';
import { View } from './view';
export interface ConditionState { export interface ConditionState {
view?: Readonly<View>; view?: string;
fullscreen?: boolean; fullscreen?: boolean;
camera?: CameraConfig; camera?: string;
} }
class ConditionStateRequestEvent extends Event { class ConditionStateRequestEvent extends Event {
@@ -26,41 +23,14 @@ export function evaluateCondition(
} }
let result = true; let result = true;
if (condition?.view?.length && state.view) { if (condition?.view?.length) {
result &&= condition?.view.includes(state.view.view); result &&= !!state.view && condition.view.includes(state.view);
} }
if (condition?.fullscreen !== undefined && state.fullscreen !== undefined) { if (condition?.fullscreen !== undefined) {
result &&= condition?.fullscreen == state.fullscreen; result &&= state.fullscreen !== undefined && condition.fullscreen == state.fullscreen;
} }
if (condition?.camera?.length) {
const evaluateNested = ( result &&= !!state.camera && condition.camera.includes(state.camera);
input: Readonly<RawFrigateCardConfig>,
condition: Readonly<RawFrigateCardConfig>,
): boolean => {
let result = true;
for (const key of Object.keys(condition)) {
if (typeof condition[key] === 'string') {
// If the test is a literal, it must exactly match.
result &&= input[key] === condition[key];
} else if (Array.isArray(condition[key])) {
// If the test is an array, it's a list of acceptable values.
result &&= (condition[key] as unknown[]).includes(input[key]);
} else if (typeof condition[key] === 'object' && typeof input[key] === 'object') {
// If the test is an object, recursively navigate downwards.
result &&= evaluateNested(
input[key] as RawFrigateCardConfig,
condition[key] as RawFrigateCardConfig,
);
} else if (input[key] === undefined) {
return false;
}
}
return result;
};
if (condition?.camera) {
result &&= state.camera ? evaluateNested(state.camera, condition.camera) : false;
} }
return result; return result;
} }
+2 -3
View File
@@ -222,10 +222,9 @@ export class FrigateCard extends LitElement {
*/ */
protected _generateConditionState(): void { protected _generateConditionState(): void {
this._conditionState = { this._conditionState = {
view: this._view, view: this._view?.view,
fullscreen: screenfull.isEnabled && screenfull.isFullscreen, fullscreen: screenfull.isEnabled && screenfull.isFullscreen,
camera: camera: this._view?.camera,
this._cameras && this._view ? this._cameras.get(this._view.camera) : undefined,
}; };
} }
+6 -5
View File
@@ -1,7 +1,7 @@
// TODO different live configs per camera // TODO different live configs per camera
// TODO evaluate single override section instead of per-subcomponent // TODO evaluate single override section instead of per-subcomponent
// TODO Remove id as a concept for cameras and use an array instead?
// TODO Convert menu condition to use overrides // TODO Convert menu condition to use overrides
// TODO Fix overlapping menu icon issue.
// TODO Remove media load event console message // TODO Remove media load event console message
// TODO Remove view change console message // TODO Remove view change console message
// TODO readme // TODO readme
@@ -309,10 +309,10 @@ export class FrigateCardLiveCarousel extends FrigateCardMediaCarousel {
const slides: TemplateResult[] = []; const slides: TemplateResult[] = [];
const cameraToSlide: Record<string, number> = {}; const cameraToSlide: Record<string, number> = {};
for (const [key, value] of this.cameras) { for (const [camera, cameraConfig] of this.cameras) {
const slide = this._renderLive(value, slides.length); const slide = this._renderLive(camera, cameraConfig, slides.length);
if (slide) { if (slide) {
cameraToSlide[key] = slides.length; cameraToSlide[camera] = slides.length;
slides.push(slide); slides.push(slide);
} }
} }
@@ -351,6 +351,7 @@ export class FrigateCardLiveCarousel extends FrigateCardMediaCarousel {
} }
protected _renderLive( protected _renderLive(
camera: string,
cameraConfig: CameraConfig, cameraConfig: CameraConfig,
slideIndex: number, slideIndex: number,
): TemplateResult | void { ): TemplateResult | void {
@@ -362,7 +363,7 @@ export class FrigateCardLiveCarousel extends FrigateCardMediaCarousel {
// <frigate-card-live-provider> is rendering right now. // <frigate-card-live-provider> is rendering right now.
const conditionState = Object.assign({ const conditionState = Object.assign({
...this.conditionState, ...this.conditionState,
camera: cameraConfig, camera: camera,
}); });
const config = getOverriddenConfig(this.liveConfig, conditionState) as LiveConfig; const config = getOverriddenConfig(this.liveConfig, conditionState) as LiveConfig;
+1 -3
View File
@@ -349,9 +349,7 @@ export type MenuSubmenu = z.infer<typeof menuSubmenuSchema>;
const frigateCardConditionSchema = z.object({ const frigateCardConditionSchema = z.object({
view: z.string().array().optional(), view: z.string().array().optional(),
fullscreen: z.boolean().optional(), fullscreen: z.boolean().optional(),
camera: z.string().array().optional(),
// Allow matching any field of cameraConfig.
camera: z.record(z.any()),
}); });
export type FrigateCardCondition = z.infer<typeof frigateCardConditionSchema>; export type FrigateCardCondition = z.infer<typeof frigateCardConditionSchema>;