@@ -22,7 +22,6 @@ export class ConditionsManager implements ConditionsManagerReadonlyInterface {
|
||||
|
||||
protected _listeners: ConditionsListener[] = [];
|
||||
protected _mediaQueries: MediaQueryList[] = [];
|
||||
protected _hasHAStateConditions = false;
|
||||
protected _evaluation: ConditionsEvaluationResult = { result: false };
|
||||
|
||||
constructor(
|
||||
@@ -30,13 +29,6 @@ export class ConditionsManager implements ConditionsManagerReadonlyInterface {
|
||||
stateManager?: ConditionStateManagerReadonlyInterface | null,
|
||||
) {
|
||||
this._conditions = conditions;
|
||||
|
||||
this._hasHAStateConditions = conditions.some(
|
||||
(condition) =>
|
||||
!condition.condition ||
|
||||
['state', 'numeric_state', 'user'].includes(condition.condition),
|
||||
);
|
||||
|
||||
conditions.forEach((condition) => {
|
||||
if (condition.condition === 'screen') {
|
||||
const mql = window.matchMedia(condition.media_query);
|
||||
@@ -82,17 +74,6 @@ export class ConditionsManager implements ConditionsManagerReadonlyInterface {
|
||||
protected _mediaQueryHandler = () => this._evaluate();
|
||||
|
||||
protected _stateManagerHandler = (stateChange: ConditionStateChange): void => {
|
||||
// As a performance optmization, if only Home Assistant state has changed
|
||||
// (very frequent), and there aren't any related conditions, don't bother
|
||||
// calling for the evealuation / listeners.
|
||||
if (
|
||||
Object.keys(stateChange.change).length === 1 &&
|
||||
'state' in stateChange.change &&
|
||||
!this._hasHAStateConditions
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._evaluate({ stateChange });
|
||||
};
|
||||
|
||||
@@ -324,6 +305,42 @@ export class ConditionsManager implements ConditionsManagerReadonlyInterface {
|
||||
}
|
||||
case 'initialized':
|
||||
return { result: !!newState?.initialized };
|
||||
case 'or':
|
||||
for (const subCondition of condition.conditions) {
|
||||
const evaluation = this._evaluateCondition(subCondition, newState, oldState);
|
||||
if (evaluation.result) {
|
||||
return evaluation;
|
||||
}
|
||||
}
|
||||
return { result: false };
|
||||
case 'and': {
|
||||
let triggerData: ConditionsTriggerData = {};
|
||||
for (const subCondition of condition.conditions) {
|
||||
const evaluation = this._evaluateCondition(subCondition, newState, oldState);
|
||||
if (!evaluation.result) {
|
||||
return { result: false };
|
||||
}
|
||||
triggerData = {
|
||||
...triggerData,
|
||||
...evaluation.triggerData,
|
||||
};
|
||||
}
|
||||
return { result: true, triggerData };
|
||||
}
|
||||
case 'not': {
|
||||
// "Not" is just an inversed `and`. There is no trigger data for "not
|
||||
// triggering".
|
||||
return {
|
||||
result: !this._evaluateCondition(
|
||||
{
|
||||
...condition,
|
||||
condition: 'and',
|
||||
},
|
||||
newState,
|
||||
oldState,
|
||||
).result,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,12 +17,54 @@ import { screenConditionSchema } from './stock/screen';
|
||||
import { stateConditionSchema } from './stock/state';
|
||||
import { usersConditionSchema } from './stock/users';
|
||||
|
||||
export const advancedCameraCardConditionSchema = z.discriminatedUnion('condition', [
|
||||
// https://www.home-assistant.io/docs/scripts/conditions/#or-condition
|
||||
type OrCondition = {
|
||||
condition: 'or';
|
||||
conditions: AdvancedCameraCardCondition[];
|
||||
};
|
||||
const orConditionSchema: z.ZodSchema<OrCondition> = z.object({
|
||||
condition: z.literal('or'),
|
||||
conditions: z
|
||||
.lazy(() => advancedCameraCardConditionSchema)
|
||||
.array()
|
||||
.min(1),
|
||||
});
|
||||
|
||||
// https://www.home-assistant.io/docs/scripts/conditions/#and-condition
|
||||
type AndCondition = {
|
||||
condition: 'and';
|
||||
conditions: AdvancedCameraCardCondition[];
|
||||
};
|
||||
const andConditionSchema: z.ZodSchema<AndCondition> = z.object({
|
||||
condition: z.literal('and'),
|
||||
conditions: z
|
||||
.lazy(() => advancedCameraCardConditionSchema)
|
||||
.array()
|
||||
.min(1),
|
||||
});
|
||||
|
||||
// https://www.home-assistant.io/docs/scripts/conditions/#not-condition
|
||||
type NotCondition = {
|
||||
condition: 'not';
|
||||
conditions: AdvancedCameraCardCondition[];
|
||||
};
|
||||
const notConditionSchema: z.ZodSchema<NotCondition> = z.object({
|
||||
condition: z.literal('not'),
|
||||
conditions: z
|
||||
.lazy(() => advancedCameraCardConditionSchema)
|
||||
.array()
|
||||
.min(1),
|
||||
});
|
||||
|
||||
export const advancedCameraCardConditionSchema = z.union([
|
||||
// Stock conditions:
|
||||
numericStateConditionSchema,
|
||||
screenConditionSchema,
|
||||
stateConditionSchema,
|
||||
usersConditionSchema,
|
||||
orConditionSchema,
|
||||
andConditionSchema,
|
||||
notConditionSchema,
|
||||
|
||||
// Custom conditions:
|
||||
cameraConditionSchema,
|
||||
|
||||
Reference in New Issue
Block a user