Compare commits

...

4 Commits

Author SHA1 Message Date
Paul Bottein 073b4bfb91 Use checkStrategyShouldRegenerate in views, sections, and panels
Replace hardcoded registry checks with checkStrategyShouldRegenerate
in hui-view, hui-section, ha-panel-lovelace, and ha-panel-home.
Regeneration checks are also extended to sections (previously only
dashboards and views were checked).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 15:12:38 +02:00
Paul Bottein 8da8f4b6d8 Add registryDependencies to all built-in strategies
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 15:12:38 +02:00
Paul Bottein 97acff0634 Add registryDependencies and checkStrategyShouldRegenerate to strategy interface
Strategies can now declare which registries they depend on via a static
`registryDependencies` property. A `shouldRegenerate` method can also
be implemented for custom logic. The `checkStrategyShouldRegenerate`
helper uses these to decide whether regeneration is needed, falling
back to checking entities, devices, areas, and floors by default.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 15:12:38 +02:00
Paul Bottein 7656a40d4e Refactor lovelace view lifecycle to avoid unnecessary DOM rebuilds
- Remove `force` flag from `hui-root` that was clearing the entire view
  cache and destroying all cached view DOM on any config change. Views
  now receive updated lovelace in place and handle config changes
  internally.
- Add `_cleanupViewCache` to remove stale cache entries when views are
  added, removed, or reordered.
- Remove `@ll-rebuild` handler from `hui-root`. Cards and badges already
  handle `ll-rebuild` via their `hui-card`/`hui-badge` wrappers. Sections
  now always stop propagation and rebuild locally.
- Add `deepEqual` guard in `hui-view._setConfig` and
  `hui-section._initializeConfig` to skip re-rendering when strategy
  regeneration produces an identical config.
- Simplify `hui-view` refresh flow: remove `_refreshConfig`,
  `_rendered` flag, `strategy-config-changed` event, and
  connected/disconnected callbacks. Registry changes now debounce
  directly into `_initializeConfig`.
- Fix `isStrategy` check in `hui-view._initializeConfig` to use the raw
  config (before strategy expansion) rather than the generated config.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 15:12:38 +02:00
22 changed files with 229 additions and 100 deletions
@@ -5,10 +5,13 @@ import { getEnergyDataCollection } from "../../../data/energy";
import type { HomeAssistant } from "../../../types";
import type { LovelaceViewConfig } from "../../../data/lovelace/config/view";
import type { LovelaceStrategyConfig } from "../../../data/lovelace/config/strategy";
import type { LovelaceStrategyRegistryKey } from "../../lovelace/strategies/types";
import { DEFAULT_ENERGY_COLLECTION_KEY } from "../constants";
@customElement("energy-overview-view-strategy")
export class EnergyOverviewViewStrategy extends ReactiveElement {
static registryDependencies: readonly LovelaceStrategyRegistryKey[] = [];
static async generate(
_config: LovelaceStrategyConfig,
hass: HomeAssistant
@@ -12,9 +12,12 @@ import {
LARGE_SCREEN_CONDITION,
SMALL_SCREEN_CONDITION,
} from "../../lovelace/strategies/helpers/view-columns-conditions";
import type { LovelaceStrategyRegistryKey } from "../../lovelace/strategies/types";
@customElement("energy-view-strategy")
export class EnergyViewStrategy extends ReactiveElement {
static registryDependencies: readonly LovelaceStrategyRegistryKey[] = [];
static async generate(
_config: LovelaceStrategyConfig,
hass: HomeAssistant
@@ -6,9 +6,12 @@ import type { LovelaceViewConfig } from "../../../data/lovelace/config/view";
import type { LovelaceStrategyConfig } from "../../../data/lovelace/config/strategy";
import { DEFAULT_ENERGY_COLLECTION_KEY } from "../constants";
import type { LovelaceSectionConfig } from "../../../data/lovelace/config/section";
import type { LovelaceStrategyRegistryKey } from "../../lovelace/strategies/types";
@customElement("gas-view-strategy")
export class GasViewStrategy extends ReactiveElement {
static registryDependencies: readonly LovelaceStrategyRegistryKey[] = [];
static async generate(
_config: LovelaceStrategyConfig,
hass: HomeAssistant
@@ -8,9 +8,12 @@ import { DEFAULT_ENERGY_COLLECTION_KEY } from "../constants";
import { shouldShowFloorsAndAreas } from "./show-floors-and-areas";
import type { LovelaceSectionConfig } from "../../../data/lovelace/config/section";
import type { LovelaceBadgeConfig } from "../../../data/lovelace/config/badge";
import type { LovelaceStrategyRegistryKey } from "../../lovelace/strategies/types";
@customElement("power-view-strategy")
export class PowerViewStrategy extends ReactiveElement {
static registryDependencies: readonly LovelaceStrategyRegistryKey[] = [];
static async generate(
_config: LovelaceStrategyConfig,
hass: HomeAssistant
@@ -5,11 +5,14 @@ import type { LovelaceSectionConfig } from "../../../data/lovelace/config/sectio
import type { LovelaceStrategyConfig } from "../../../data/lovelace/config/strategy";
import type { LovelaceViewConfig } from "../../../data/lovelace/config/view";
import type { HomeAssistant } from "../../../types";
import type { LovelaceStrategyRegistryKey } from "../../lovelace/strategies/types";
import { DEFAULT_ENERGY_COLLECTION_KEY } from "../constants";
import { shouldShowFloorsAndAreas } from "./show-floors-and-areas";
@customElement("water-view-strategy")
export class WaterViewStrategy extends ReactiveElement {
static registryDependencies: readonly LovelaceStrategyRegistryKey[] = [];
static async generate(
_config: LovelaceStrategyConfig,
hass: HomeAssistant
+29 -36
View File
@@ -7,7 +7,6 @@ import { styleMap } from "lit/directives/style-map";
import { atLeastVersion } from "../../common/config/version";
import { navigate } from "../../common/navigate";
import { debounce } from "../../common/util/debounce";
import { deepEqual } from "../../common/util/deep-equal";
import "../../components/ha-button";
import "../../components/ha-svg-icon";
import { updateAreaRegistryEntry } from "../../data/area/area_registry";
@@ -26,7 +25,10 @@ import { showDeviceRegistryDetailDialog } from "../config/devices/device-registr
import { showAddIntegrationDialog } from "../config/integrations/show-add-integration-dialog";
import "../lovelace/hui-root";
import type { ExtraActionItem } from "../lovelace/hui-root";
import { expandLovelaceConfigStrategies } from "../lovelace/strategies/get-strategy";
import {
checkStrategyShouldRegenerate,
generateLovelaceDashboardStrategy,
} from "../lovelace/strategies/get-strategy";
import type { Lovelace } from "../lovelace/types";
import { showEditHomeDialog } from "./dialogs/show-dialog-edit-home";
import { showNewOverviewDialog } from "./dialogs/show-dialog-new-overview";
@@ -99,26 +101,19 @@ class PanelHome extends LitElement {
return;
}
if (oldHass && this.hass) {
// If the entity registry changed, ask the user if they want to refresh the config
if (
oldHass.entities !== this.hass.entities ||
oldHass.devices !== this.hass.devices ||
oldHass.areas !== this.hass.areas ||
oldHass.floors !== this.hass.floors ||
oldHass.panels !== this.hass.panels
) {
if (this.hass.config.state === "RUNNING") {
this._debounceRegistriesChanged();
return;
}
}
// If ha started, refresh the config
if (
this.hass.config.state === "RUNNING" &&
oldHass.config.state !== "RUNNING"
) {
if (oldHass && this.hass && this.hass.config.state === "RUNNING") {
if (oldHass.config.state !== "RUNNING") {
this._setup();
return;
}
const shouldRegenerate = checkStrategyShouldRegenerate(
"dashboard",
this._strategyConfig.strategy,
oldHass,
this.hass
);
if (shouldRegenerate) {
this._debounceRegenerateStrategy();
}
}
}
@@ -144,12 +139,12 @@ class PanelHome extends LitElement {
}
}
private _debounceRegistriesChanged = debounce(
() => this._registriesChanged(),
private _debounceRegenerateStrategy = debounce(
() => this._regenerateStrategyConfig(),
200
);
private _registriesChanged = async () => {
private _regenerateStrategyConfig() {
// If on an area view that no longer exists, redirect to overview
const path = this.route?.path?.split("/")[1];
if (path?.startsWith("areas-")) {
@@ -160,7 +155,7 @@ class PanelHome extends LitElement {
}
}
this._setLovelace();
};
}
private _updateExtraActionItems() {
const path = this.route?.path?.split("/")[1];
@@ -320,11 +315,8 @@ class PanelHome extends LitElement {
});
}
private async _setLovelace() {
if (this._loadConfigPromise) {
await this._loadConfigPromise;
}
const strategyConfig: LovelaceDashboardStrategyConfig = {
private get _strategyConfig(): LovelaceDashboardStrategyConfig {
return {
strategy: {
type: "home",
favorite_entities: this._config.favorite_entities,
@@ -334,16 +326,17 @@ class PanelHome extends LitElement {
shortcuts: this._config.shortcuts,
},
};
}
const config = await expandLovelaceConfigStrategies(
strategyConfig,
private async _setLovelace() {
if (this._loadConfigPromise) {
await this._loadConfigPromise;
}
const config = await generateLovelaceDashboardStrategy(
this._strategyConfig,
this.hass
);
if (deepEqual(config, this._lovelace?.config)) {
return;
}
this._lovelace = {
config: config,
rawConfig: config,
+14 -54
View File
@@ -12,7 +12,6 @@ import {
removeSearchParam,
} from "../../common/url/search-params";
import { debounce } from "../../common/util/debounce";
import { deepEqual } from "../../common/util/deep-equal";
import "../../components/ha-button";
import { domainToName } from "../../data/integration";
import { subscribeLovelaceUpdates } from "../../data/lovelace";
@@ -36,7 +35,10 @@ import { checkLovelaceConfig } from "./common/check-lovelace-config";
import { loadLovelaceResources } from "./common/load-resources";
import { showSaveDialog } from "./editor/show-save-config-dialog";
import "./hui-root";
import { generateLovelaceDashboardStrategy } from "./strategies/get-strategy";
import {
checkStrategyShouldRegenerate,
generateLovelaceDashboardStrategy,
} from "./strategies/get-strategy";
import type { Lovelace } from "./types";
import { generateDefaultView } from "./views/default-view";
import { fetchDashboards } from "../../data/lovelace/dashboard";
@@ -50,12 +52,6 @@ interface LovelacePanelConfig {
let editorLoaded = false;
let resourcesLoaded = false;
declare global {
interface HASSDomEvents {
"strategy-config-changed": undefined;
}
}
@customElement("ha-panel-lovelace")
export class LovelacePanel extends LitElement {
@property({ attribute: false }) public panel?: PanelInfo<
@@ -129,7 +125,6 @@ export class LovelacePanel extends LitElement {
.route=${this.route}
.narrow=${this.narrow}
@config-refresh=${this._forceFetchConfig}
@strategy-config-changed=${this._strategyConfigChanged}
></hui-root>
`;
}
@@ -195,61 +190,26 @@ export class LovelacePanel extends LitElement {
this.lovelace &&
isStrategyDashboard(this.lovelace.rawConfig)
) {
// If the entity registry changed, ask the user if they want to refresh the config
if (
oldHass.entities !== this.hass.entities ||
oldHass.devices !== this.hass.devices ||
oldHass.areas !== this.hass.areas ||
oldHass.floors !== this.hass.floors
) {
if (this.hass.config.state === "RUNNING") {
this._debounceRegistriesChanged();
}
}
// If ha started, refresh the config
if (
this.hass.config.state === "RUNNING" &&
oldHass.config.state !== "RUNNING"
(oldHass.config.state !== "RUNNING" ||
checkStrategyShouldRegenerate(
"dashboard",
this.lovelace.rawConfig.strategy,
oldHass,
this.hass
))
) {
this._regenerateStrategyConfig();
this._debounceRegenerateStrategy();
}
}
}
private _debounceRegistriesChanged = debounce(
() => this._registriesChanged(),
private _debounceRegenerateStrategy = debounce(
() => this._regenerateStrategyConfig(),
200
);
private _registriesChanged = async () => {
if (!this.hass || !this.lovelace) {
return;
}
const rawConfig = this.lovelace.rawConfig;
if (!isStrategyDashboard(rawConfig)) {
return;
}
const oldConfig = this.lovelace.config;
const generatedConfig = await generateLovelaceDashboardStrategy(
rawConfig,
this.hass!
);
const newConfig = checkLovelaceConfig(generatedConfig) as LovelaceConfig;
// Regenerate if the config changed
if (!deepEqual(newConfig, oldConfig)) {
this._regenerateStrategyConfig();
}
};
private _strategyConfigChanged = (ev: CustomEvent) => {
ev.stopPropagation();
this._regenerateStrategyConfig();
};
private async _regenerateStrategyConfig() {
if (!this.hass || !this.lovelace) {
return;
+32 -1
View File
@@ -6,6 +6,7 @@ import { storage } from "../../../common/decorators/storage";
import { deepEqual } from "../../../common/util/deep-equal";
import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element";
import { fireEvent } from "../../../common/dom/fire_event";
import { debounce } from "../../../common/util/debounce";
import "../../../components/ha-svg-icon";
import type { LovelaceSectionElement } from "../../../data/lovelace";
import type { LovelaceCardConfig } from "../../../data/lovelace/config/card";
@@ -25,7 +26,10 @@ import { showEditCardDialog } from "../editor/card-editor/show-edit-card-dialog"
import { addCard, replaceCard } from "../editor/config-util";
import { performDeleteCard } from "../editor/delete-card";
import { parseLovelaceCardPath } from "../editor/lovelace-path";
import { generateLovelaceSectionStrategy } from "../strategies/get-strategy";
import {
checkStrategyShouldRegenerate,
generateLovelaceSectionStrategy,
} from "../strategies/get-strategy";
import type { Lovelace } from "../types";
import { DEFAULT_SECTION_LAYOUT } from "./const";
@@ -106,9 +110,36 @@ export class HuiSection extends ConditionalListenerMixin<LovelaceSectionConfig>(
(!oldConfig || this.config !== oldConfig)
) {
this._initializeConfig();
return;
}
if (!changedProperties.has("hass")) {
return;
}
const oldHass = changedProperties.get("hass") as HomeAssistant | undefined;
if (
oldHass &&
this.hass &&
isStrategySection(this.config) &&
this.hass.config.state === "RUNNING" &&
(oldHass.config.state !== "RUNNING" ||
checkStrategyShouldRegenerate(
"section",
this.config.strategy,
oldHass,
this.hass
))
) {
this._debounceRefreshConfig();
}
}
private _debounceRefreshConfig = debounce(
() => this._initializeConfig(),
200
);
public disconnectedCallback() {
super.disconnectedCallback();
this.removeEventListener(
@@ -6,6 +6,7 @@ import type { LovelaceCardConfig } from "../../../../data/lovelace/config/card";
import type { LovelaceSectionRawConfig } from "../../../../data/lovelace/config/section";
import type { LovelaceViewConfig } from "../../../../data/lovelace/config/view";
import type { HomeAssistant } from "../../../../types";
import type { LovelaceStrategyRegistryKey } from "../types";
import {
AREA_STRATEGY_GROUP_ICONS,
computeAreaTileCardConfig,
@@ -34,6 +35,12 @@ const computeHeadingCard = (
@customElement("area-view-strategy")
export class AreaViewStrategy extends ReactiveElement {
static registryDependencies: readonly LovelaceStrategyRegistryKey[] = [
"entities",
"devices",
"areas",
];
static async generate(
config: AreaViewStrategyConfig,
hass: HomeAssistant
@@ -4,7 +4,10 @@ import { customElement } from "lit/decorators";
import type { LovelaceConfig } from "../../../../data/lovelace/config/types";
import type { LovelaceViewRawConfig } from "../../../../data/lovelace/config/view";
import type { HomeAssistant } from "../../../../types";
import type { LovelaceStrategyEditor } from "../types";
import type {
LovelaceStrategyEditor,
LovelaceStrategyRegistryKey,
} from "../types";
import type {
AreaViewStrategyConfig,
EntitiesDisplay,
@@ -31,6 +34,10 @@ export interface AreasDashboardStrategyConfig {
@customElement("areas-dashboard-strategy")
export class AreasDashboardStrategy extends ReactiveElement {
static registryDependencies: readonly LovelaceStrategyRegistryKey[] = [
"areas",
];
static async generate(
config: AreasDashboardStrategyConfig,
hass: HomeAssistant
@@ -23,12 +23,20 @@ import type {
LovelaceDashboardStrategyGetCreateSuggestions,
LovelaceSectionStrategy,
LovelaceStrategy,
LovelaceStrategyRegistryKey,
LovelaceViewStrategy,
} from "./types";
const MAX_WAIT_STRATEGY_LOAD = 5000;
const CUSTOM_PREFIX = "custom:";
const DEFAULT_REGISTRY_DEPENDENCIES: readonly LovelaceStrategyRegistryKey[] = [
"entities",
"devices",
"areas",
"floors",
];
const STRATEGIES: Record<LovelaceStrategyConfigType, Record<string, any>> = {
dashboard: {
"original-states": () =>
@@ -241,6 +249,48 @@ export const generateLovelaceSectionStrategy = async (
};
};
/**
* Synchronously checks whether a strategy needs regeneration.
* Strategies can implement `shouldRegenerate` for custom logic or declare
* `registryDependencies` to opt in to the default reference-equality check.
* The default list (entities, devices, areas, floors) is used when neither is
* provided, preserving the previous behavior for third-party strategies.
*/
export const checkStrategyShouldRegenerate = (
configType: LovelaceStrategyConfigType,
strategyConfig: LovelaceStrategyConfig,
oldHass: HomeAssistant,
newHass: HomeAssistant
): boolean => {
const strategyType = strategyConfig.type;
if (!strategyType) {
return false;
}
let strategy: LovelaceStrategy | undefined;
if (strategyType in STRATEGIES[configType]) {
const tag = `${strategyType}-${configType}-strategy`;
strategy = customElements.get(tag) as unknown as
| LovelaceStrategy
| undefined;
} else if (strategyType.startsWith(CUSTOM_PREFIX)) {
const name = strategyType.slice(CUSTOM_PREFIX.length);
const tag = `ll-strategy-${configType}-${name}`;
const legacyTag = `ll-strategy-${name}`;
strategy = (customElements.get(tag) ??
customElements.get(legacyTag)) as unknown as LovelaceStrategy | undefined;
}
if (strategy?.shouldRegenerate) {
return strategy.shouldRegenerate(strategyConfig, oldHass, newHass);
}
const dependencies =
strategy?.registryDependencies ?? DEFAULT_REGISTRY_DEPENDENCIES;
return dependencies.some((key) => oldHass[key] !== newHass[key]);
};
/**
* Find all references to strategies and replaces them with the generated output
*/
@@ -17,6 +17,7 @@ import type {
} from "../../cards/types";
import type { ButtonHeadingBadgeConfig } from "../../heading-badges/types";
import { computeAreaTileCardConfig } from "../areas/helpers/areas-strategy-helper";
import type { LovelaceStrategyRegistryKey } from "../types";
import {
getSummaryLabel,
HOME_SUMMARIES,
@@ -33,6 +34,13 @@ export interface HomeAreaViewStrategyConfig {
@customElement("home-area-view-strategy")
export class HomeAreaViewStrategy extends ReactiveElement {
static registryDependencies: readonly LovelaceStrategyRegistryKey[] = [
"entities",
"devices",
"areas",
"panels",
];
static async generate(
config: HomeAreaViewStrategyConfig,
hass: HomeAssistant
@@ -4,7 +4,10 @@ import { customElement } from "lit/decorators";
import type { LovelaceConfig } from "../../../../data/lovelace/config/types";
import type { LovelaceViewRawConfig } from "../../../../data/lovelace/config/view";
import type { HomeAssistant } from "../../../../types";
import type { LovelaceStrategyEditor } from "../types";
import type {
LovelaceStrategyEditor,
LovelaceStrategyRegistryKey,
} from "../types";
import {
getSummaryLabel,
HOME_SUMMARIES_ICONS,
@@ -25,6 +28,10 @@ export interface HomeDashboardStrategyConfig {
@customElement("home-dashboard-strategy")
export class HomeDashboardStrategy extends ReactiveElement {
static registryDependencies: readonly LovelaceStrategyRegistryKey[] = [
"areas",
];
static async generate(
config: HomeDashboardStrategyConfig,
hass: HomeAssistant
@@ -35,6 +35,7 @@ import {
LARGE_SCREEN_CONDITION,
SMALL_SCREEN_CONDITION,
} from "../helpers/view-columns-conditions";
import type { LovelaceStrategyRegistryKey } from "../types";
import type { CommonControlsSectionStrategyConfig } from "../usage_prediction/common-controls-section-strategy";
import { HOME_SUMMARIES_FILTERS } from "./helpers/home-summaries";
import { OTHER_DEVICES_FILTERS } from "./helpers/other-devices-filters";
@@ -79,6 +80,14 @@ const computeAreaCard = (
@customElement("home-overview-view-strategy")
export class HomeOverviewViewStrategy extends ReactiveElement {
static registryDependencies: readonly LovelaceStrategyRegistryKey[] = [
"entities",
"devices",
"areas",
"floors",
"panels",
];
static async generate(
config: HomeOverviewViewStrategyConfig,
hass: HomeAssistant
@@ -1,13 +1,18 @@
import { ReactiveElement } from "lit";
import { customElement } from "lit/decorators";
import type { LovelaceConfig } from "../../../../data/lovelace/config/types";
import type { LovelaceStrategyEditor } from "../types";
import type {
LovelaceStrategyEditor,
LovelaceStrategyRegistryKey,
} from "../types";
import type { IframeViewStrategyConfig } from "./iframe-view-strategy";
export type IframeDashboardStrategyConfig = IframeViewStrategyConfig;
@customElement("iframe-dashboard-strategy")
export class IframeDashboardStrategy extends ReactiveElement {
static registryDependencies: readonly LovelaceStrategyRegistryKey[] = [];
static async generate(
config: IframeDashboardStrategyConfig
): Promise<LovelaceConfig> {
@@ -2,6 +2,7 @@ import { ReactiveElement } from "lit";
import { customElement } from "lit/decorators";
import type { LovelaceViewConfig } from "../../../../data/lovelace/config/view";
import type { IframeCardConfig } from "../../cards/types";
import type { LovelaceStrategyRegistryKey } from "../types";
export interface IframeViewStrategyConfig {
type: "iframe";
@@ -11,6 +12,8 @@ export interface IframeViewStrategyConfig {
@customElement("iframe-view-strategy")
export class IframeViewStrategy extends ReactiveElement {
static registryDependencies: readonly LovelaceStrategyRegistryKey[] = [];
static async generate(
config: IframeViewStrategyConfig
): Promise<LovelaceViewConfig> {
@@ -3,12 +3,15 @@ import { customElement } from "lit/decorators";
import type { LovelaceDashboardSuggestions } from "../../../../data/lovelace/dashboard";
import type { LovelaceConfig } from "../../../../data/lovelace/config/types";
import type { HomeAssistant } from "../../../../types";
import type { LovelaceStrategyRegistryKey } from "../types";
import type { MapViewStrategyConfig } from "./map-view-strategy";
export type MapDashboardStrategyConfig = MapViewStrategyConfig;
@customElement("map-dashboard-strategy")
export class MapDashboardStrategy extends ReactiveElement {
static registryDependencies: readonly LovelaceStrategyRegistryKey[] = [];
static async generate(
config: MapDashboardStrategyConfig
): Promise<LovelaceConfig> {
@@ -3,6 +3,7 @@ import { customElement } from "lit/decorators";
import type { LovelaceViewConfig } from "../../../../data/lovelace/config/view";
import type { HomeAssistant } from "../../../../types";
import type { MapCardConfig } from "../../cards/types";
import type { LovelaceStrategyRegistryKey } from "../types";
export interface MapViewStrategyConfig {
type: "map";
@@ -10,6 +11,8 @@ export interface MapViewStrategyConfig {
@customElement("map-view-strategy")
export class MapViewStrategy extends ReactiveElement {
static registryDependencies: readonly LovelaceStrategyRegistryKey[] = [];
static async generate(
_config: MapViewStrategyConfig,
hass: HomeAssistant
@@ -1,7 +1,10 @@
import { ReactiveElement } from "lit";
import { customElement } from "lit/decorators";
import type { LovelaceConfig } from "../../../../data/lovelace/config/types";
import type { LovelaceStrategyEditor } from "../types";
import type {
LovelaceStrategyEditor,
LovelaceStrategyRegistryKey,
} from "../types";
import type { OriginalStatesViewStrategyConfig } from "./original-states-view-strategy";
export type OriginalStatesDashboardStrategyConfig =
@@ -9,6 +12,8 @@ export type OriginalStatesDashboardStrategyConfig =
@customElement("original-states-dashboard-strategy")
export class OriginalStatesDashboardStrategy extends ReactiveElement {
static registryDependencies: readonly LovelaceStrategyRegistryKey[] = [];
static async generate(
config: OriginalStatesDashboardStrategyConfig
): Promise<LovelaceConfig> {
+14
View File
@@ -6,8 +6,22 @@ import type { LovelaceViewConfig } from "../../../data/lovelace/config/view";
import type { HomeAssistant } from "../../../types";
import type { LovelaceGenericElementEditor } from "../types";
export type LovelaceStrategyRegistryKey =
| "entities"
| "devices"
| "areas"
| "floors"
| "labels"
| "panels";
export interface LovelaceStrategy<T = any> {
generate(config: LovelaceStrategyConfig, hass: HomeAssistant): Promise<T>;
shouldRegenerate?(
config: LovelaceStrategyConfig,
oldHass: HomeAssistant,
newHass: HomeAssistant
): boolean;
registryDependencies?: readonly LovelaceStrategyRegistryKey[];
getConfigElement?: () => LovelaceStrategyEditor;
noEditor?: boolean;
configRequired?: boolean;
@@ -6,6 +6,7 @@ import { getCommonControlsUsagePrediction } from "../../../../data/usage_predict
import type { HomeAssistant } from "../../../../types";
import type { HeadingCardConfig, TileCardConfig } from "../../cards/types";
import type { Condition } from "../../common/validate-condition";
import type { LovelaceStrategyRegistryKey } from "../types";
const DEFAULT_LIMIT = 8;
@@ -33,6 +34,8 @@ const toTileCard = (entity: string): TileCardConfig => ({
@customElement("common-controls-section-strategy")
export class CommonControlsSectionStrategy extends ReactiveElement {
static registryDependencies: readonly LovelaceStrategyRegistryKey[] = [];
static async generate(
config: CommonControlsSectionStrategyConfig,
hass: HomeAssistant
+11 -5
View File
@@ -42,7 +42,10 @@ import { parseLovelaceCardPath } from "../editor/lovelace-path";
import { createErrorSectionConfig } from "../sections/hui-error-section";
import "../sections/hui-section";
import type { HuiSection } from "../sections/hui-section";
import { generateLovelaceViewStrategy } from "../strategies/get-strategy";
import {
checkStrategyShouldRegenerate,
generateLovelaceViewStrategy,
} from "../strategies/get-strategy";
import type { Lovelace } from "../types";
import { getViewType } from "./get-view-type";
@@ -185,10 +188,13 @@ export class HUIView extends ReactiveElement {
if (oldHass && this.hass && this.lovelace && isStrategyView(viewConfig)) {
if (
this.hass.config.state === "RUNNING" &&
(oldHass.entities !== this.hass.entities ||
oldHass.devices !== this.hass.devices ||
oldHass.areas !== this.hass.areas ||
oldHass.floors !== this.hass.floors)
(oldHass.config.state !== "RUNNING" ||
checkStrategyShouldRegenerate(
"view",
viewConfig.strategy,
oldHass,
this.hass
))
) {
this._debounceRefreshConfig();
}