Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Avoid re-rendering map with "sources" #18635

Merged
merged 11 commits into from
Nov 28, 2023
109 changes: 67 additions & 42 deletions src/panels/lovelace/cards/hui-map-card.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,15 @@ import {
formatTimeWeekday,
} from "../../../common/datetime/format_time";
import { computeDomain } from "../../../common/entity/compute_domain";
import { deepEqual } from "../../../common/util/deep-equal";
import parseAspectRatio from "../../../common/util/parse-aspect-ratio";
import "../../../components/ha-card";
import "../../../components/ha-alert";
import "../../../components/ha-icon-button";
import "../../../components/map/ha-map";
import type {
HaMap,
HaMapEntity,
HaMapPathPoint,
HaMapPaths,
} from "../../../components/map/ha-map";
Expand Down Expand Up @@ -70,6 +72,8 @@ class HuiMapCard extends LitElement implements LovelaceCard {

private _configEntities?: MapEntityConfig[];

@state() private _mapEntities: HaMapEntity[] = [];

private _colorDict: Record<string, string> = {};

private _colorIndex = 0;
Expand Down Expand Up @@ -102,6 +106,7 @@ class HuiMapCard extends LitElement implements LovelaceCard {
this._configEntities = config.entities
? processConfigEntities<MapEntityConfig>(config.entities)
: [];
this._updateMapEntities();
}

public getCardSize(): number {
Expand Down Expand Up @@ -156,14 +161,10 @@ class HuiMapCard extends LitElement implements LovelaceCard {
<div id="root">
<ha-map
.hass=${this.hass}
.entities=${this._getEntities(
this.hass.states,
this._config,
this._configEntities
)}
.entities=${this._mapEntities}
.zoom=${this._config.default_zoom ?? DEFAULT_ZOOM}
.paths=${this._getHistoryPaths(this._config, this._stateHistory)}
.autoFit=${this._config.auto_fit}
.autoFit=${this._config.auto_fit || false}
.fitZones=${this._config.fit_zones}
.darkMode=${this._config.dark_mode}
interactiveZones
Expand All @@ -188,7 +189,6 @@ class HuiMapCard extends LitElement implements LovelaceCard {
}

const oldHass = changedProps.get("hass") as HomeAssistant | undefined;

if (!oldHass || !this._configEntities) {
return true;
}
Expand All @@ -202,7 +202,22 @@ class HuiMapCard extends LitElement implements LovelaceCard {
}

if (this._config?.geo_location_sources) {
if (oldHass.states !== this.hass.states) {
const oldSourceEntities = this._getSourceEntities(
oldHass.states,
this._config
);
const newSourceEntities = this._getSourceEntities(
this.hass.states,
this._config
);

if (
!deepEqual(oldSourceEntities, newSourceEntities) ||
amitfin marked this conversation as resolved.
Show resolved Hide resolved
newSourceEntities.some(
(entity_id) =>
oldHass.states[entity_id] !== this.hass.states[entity_id]
)
) {
return true;
}
}
Expand All @@ -212,6 +227,13 @@ class HuiMapCard extends LitElement implements LovelaceCard {
: hasConfigChanged(this, changedProps);
}

protected willUpdate(changedProps: PropertyValues): void {
super.willUpdate(changedProps);
if (changedProps.has("hass") && this._config?.geo_location_sources) {
this._updateMapEntities();
}
}

public connectedCallback() {
super.connectedCallback();
if (this.hasUpdated && this._configEntities?.length) {
Expand Down Expand Up @@ -309,46 +331,49 @@ class HuiMapCard extends LitElement implements LovelaceCard {
return color;
}

private _getEntities = memoizeOne(
(
states: HassEntities,
config: MapCardConfig,
configEntities?: MapEntityConfig[]
) => {
if (!states || !config) {
return undefined;
}
private _getSourceEntities(
states?: HassEntities,
config?: MapCardConfig
): string[] {
if (!states || !config || !config.geo_location_sources) {
return [];
}

const geoEntities: string[] = [];
if (config.geo_location_sources) {
// Calculate visible geo location sources
const includesAll = config.geo_location_sources.includes("all");
for (const stateObj of Object.values(states)) {
if (
computeDomain(stateObj.entity_id) === "geo_location" &&
(includesAll ||
config.geo_location_sources.includes(stateObj.attributes.source))
) {
geoEntities.push(stateObj.entity_id);
}
}
const geoEntities: string[] = [];
// Calculate visible geo location sources
const includesAll = config.geo_location_sources.includes("all");
for (const stateObj of Object.values(states)) {
if (
computeDomain(stateObj.entity_id) === "geo_location" &&
(includesAll ||
config.geo_location_sources.includes(stateObj.attributes.source))
) {
geoEntities.push(stateObj.entity_id);
}
}
return geoEntities;
}

return [
...(configEntities || []).map((entityConf) => ({
entity_id: entityConf.entity,
color: this._getColor(entityConf.entity),
label_mode: entityConf.label_mode,
focus: entityConf.focus,
name: entityConf.name,
})),
...geoEntities.map((entity) => ({
private _updateMapEntities(): void {
const entities = [
...(this._configEntities || []).map((entityConf) => ({
entity_id: entityConf.entity,
color: this._getColor(entityConf.entity),
label_mode: entityConf.label_mode,
focus: entityConf.focus,
name: entityConf.name,
})),
...this._getSourceEntities(this.hass?.states, this._config).map(
(entity) => ({
entity_id: entity,
color: this._getColor(entity),
})),
];
})
),
];
if (!deepEqual(entities, this._mapEntities)) {
amitfin marked this conversation as resolved.
Show resolved Hide resolved
this._mapEntities = entities;
}
);
}

private _getHistoryPaths = memoizeOne(
(
Expand Down
Loading