refactor: Significantly refactor how conditions work internally (#1886)
- Much improved API cleanliness and testability to allow further extensibility in future - Simplified code in `live` view This technically contains a small change in how overrides work in the `live` view. Since that change is _closer_ to the documentation, and since this is likely to be rarely used, this is not considered a breaking change. Previously, overrides for a given live camera would always render _as if_ that camera was selected, vs was actually selected. Now, overrides will only apply in the live view when the camera is _actually_ selected. If this is an issue for you in practice, lets discuss.
This commit is contained in:
@@ -1,14 +1,15 @@
|
||||
import { ConditionsManager } from '../conditions/conditions-manager.js';
|
||||
import { ConditionsEvaluationResult } from '../conditions/types.js';
|
||||
import { Automation, AutomationActions } from '../config/types.js';
|
||||
import { localize } from '../localize/localize.js';
|
||||
import { CardAutomationsAPI, TaggedAutomations } from './types.js';
|
||||
import { CardAutomationsAPI, TaggedAutomation } from './types.js';
|
||||
|
||||
const MAX_NESTED_AUTOMATION_EXECUTIONS = 10;
|
||||
|
||||
export class AutomationsManager {
|
||||
protected _api: CardAutomationsAPI;
|
||||
|
||||
protected _automations: TaggedAutomations = [];
|
||||
protected _priorEvaluations: Map<Automation, boolean> = new Map();
|
||||
protected _automations = new Map<TaggedAutomation, ConditionsManager>();
|
||||
|
||||
// A counter to avoid infinite loops, increases every time actions are run,
|
||||
// decreases every time actions are complete.
|
||||
@@ -19,14 +20,28 @@ export class AutomationsManager {
|
||||
}
|
||||
|
||||
public deleteAutomations(tag?: unknown) {
|
||||
this._automations = this._automations.filter((automation) => automation.tag !== tag);
|
||||
for (const [automation, conditionManager] of this._automations) {
|
||||
if (automation.tag === tag) {
|
||||
this._automations.delete(automation);
|
||||
conditionManager.destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public addAutomations(automations: TaggedAutomations): void {
|
||||
this._automations.push(...automations);
|
||||
public addAutomations(automations: TaggedAutomation[]): void {
|
||||
for (const automation of automations) {
|
||||
const conditionManager = new ConditionsManager(
|
||||
automation.conditions,
|
||||
this._api.getConditionStateManager(),
|
||||
);
|
||||
conditionManager.addListener((result: ConditionsEvaluationResult) =>
|
||||
this._execute(automation, result),
|
||||
);
|
||||
this._automations.set(automation, conditionManager);
|
||||
}
|
||||
}
|
||||
|
||||
public execute(): void {
|
||||
protected _execute(automation: Automation, result: ConditionsEvaluationResult): void {
|
||||
if (
|
||||
!this._api.getHASSManager().hasHASS() ||
|
||||
// Never execute automations if the card hasn't finished initializing, as
|
||||
@@ -40,20 +55,10 @@ export class AutomationsManager {
|
||||
return;
|
||||
}
|
||||
|
||||
const actionsToRun: AutomationActions = [];
|
||||
for (const automation of this._automations) {
|
||||
const shouldExecute = this._api
|
||||
.getConditionsManager()
|
||||
.evaluateConditions(automation.conditions);
|
||||
const actions = shouldExecute ? automation.actions : automation.actions_not;
|
||||
const priorEvaluation = this._priorEvaluations.get(automation);
|
||||
this._priorEvaluations.set(automation, shouldExecute);
|
||||
if (shouldExecute !== priorEvaluation && actions) {
|
||||
actionsToRun.push(...actions);
|
||||
}
|
||||
}
|
||||
const shouldExecute = result.result;
|
||||
const actions = shouldExecute ? automation.actions : automation.actions_not;
|
||||
|
||||
if (!actionsToRun.length) {
|
||||
if (!actions?.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -70,6 +75,6 @@ export class AutomationsManager {
|
||||
await this._api.getActionsManager().executeActions(actions);
|
||||
--this._nestedAutomationExecutions;
|
||||
};
|
||||
runActions(actionsToRun);
|
||||
runActions(actions);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user