mirror of
https://github.com/Matysh/houseplan-card
synced 2026-09-30 11:49:16 +00:00
perf: keep Zigbee route overlay within bundle guard
Issue: #457 User-Visible: no
This commit is contained in:
@@ -11779,7 +11779,7 @@ export class HouseplanCard extends LitElement {
|
||||
<svg class="iso-walls-svg" data-hp-live-viewbox="camera" viewBox="${view.x} ${view.y} ${view.w} ${view.h}"
|
||||
preserveAspectRatio="xMidYMid meet" aria-hidden="true" pointer-events="none">
|
||||
${this._renderIsoWalls(isoLayers, isoPanels)}
|
||||
</svg>` : nothing}${renderZigbeeTopologyOverlay({ hass: this.hass, settings: this._settings, devices: this._renderDevices, registry: this._haRegistry, currentSpace: space.id, spaces: this._serverCfg?.spaces || [], viewKey: view, view: this._mode === 'view', kiosk: this._kiosk })}
|
||||
</svg>` : nothing}${renderZigbeeTopologyOverlay({ hass: this.hass, settings: this._settings, devices: this._renderDevices, registry: this._haRegistry, currentSpace: space.id, spaces: this._serverCfg?.spaces, viewKey: view, view: this._mode === 'view', kiosk: this._kiosk })}
|
||||
${''/* docs/CANVAS.md §6: an icon is a percentage of the PLAN and
|
||||
scales with it when you zoom — the behaviour the card always
|
||||
had, restored by the owner. `iconCqw` is `iconPct * iconUnit
|
||||
|
||||
@@ -23,7 +23,7 @@ export class HpZigbeeTopologyOverlay extends LitElement {
|
||||
devices: { attribute: false },
|
||||
registry: { attribute: false },
|
||||
currentSpace: { type: String, attribute: 'current-space' },
|
||||
spaceTitles: { attribute: false },
|
||||
spaces: { attribute: false },
|
||||
viewKey: { attribute: false },
|
||||
};
|
||||
|
||||
@@ -31,7 +31,7 @@ export class HpZigbeeTopologyOverlay extends LitElement {
|
||||
devices: readonly DevItem[] = [];
|
||||
registry!: HaRegistrySnapshot;
|
||||
currentSpace = '';
|
||||
spaceTitles: Readonly<Record<string, string>> = {};
|
||||
spaces?: readonly { id?: unknown; title?: unknown }[];
|
||||
viewKey: unknown;
|
||||
private _runtime = EMPTY_RUNTIME;
|
||||
private _hovered = '';
|
||||
@@ -178,7 +178,8 @@ export class HpZigbeeTopologyOverlay extends LitElement {
|
||||
|
||||
private _targetText(target: ZigbeeParentTarget): string {
|
||||
if (target.kind === 'remote-space') {
|
||||
return this.spaceTitles[target.spaceId]?.trim()
|
||||
const title = this.spaces?.find((space) => space.id === target.spaceId)?.title;
|
||||
return (typeof title === 'string' && title.trim())
|
||||
|| topologyT(langOf(this.hass), 'route_other_space');
|
||||
}
|
||||
return topologyT(langOf(this.hass), target.kind === 'unplaced-coordinator'
|
||||
|
||||
@@ -4,36 +4,21 @@ import type { HaRegistrySnapshot } from './ha-binding-status';
|
||||
import type { DevItem } from './types';
|
||||
import type { ZigbeeTopologyHass } from './zigbee-topology-runtime';
|
||||
|
||||
const spaceTitleMemo = new WeakMap<object, { signature: string; titles: Readonly<Record<string, string>> }>();
|
||||
|
||||
function spaceTitlesOf(spaces: readonly { id?: unknown; title?: unknown }[]): Readonly<Record<string, string>> {
|
||||
const signature = spaces.map((space) => `${String(space.id)}\u0000${String(space.title)}`).join('\u0001');
|
||||
const cached = spaceTitleMemo.get(spaces);
|
||||
if (cached?.signature === signature) return cached.titles;
|
||||
const projected = Object.fromEntries(spaces.flatMap((space) => (
|
||||
typeof space.id === 'string' && typeof space.title === 'string'
|
||||
? [[space.id, space.title] as const] : []
|
||||
)));
|
||||
spaceTitleMemo.set(spaces, { signature, titles: projected });
|
||||
return projected;
|
||||
}
|
||||
|
||||
export function renderZigbeeTopologyOverlay(input: {
|
||||
hass: ZigbeeTopologyHass;
|
||||
settings: unknown;
|
||||
devices: readonly DevItem[];
|
||||
registry: HaRegistrySnapshot;
|
||||
currentSpace: string;
|
||||
spaces: readonly { id?: unknown; title?: unknown }[];
|
||||
spaces?: readonly { id?: unknown; title?: unknown }[];
|
||||
viewKey: unknown;
|
||||
view: boolean;
|
||||
kiosk: boolean;
|
||||
}): TemplateResult | typeof nothing {
|
||||
if (!input.view || input.kiosk || input.hass?.user?.is_admin !== true
|
||||
|| !zigbeeTopologySettingsOf(input.settings).enabled) return nothing;
|
||||
const spaceTitles = spaceTitlesOf(input.spaces);
|
||||
void import('./hp-zigbee-topology-overlay');
|
||||
return html`<hp-zigbee-topology-overlay data-hp-live-layer="camera" .hass=${input.hass} .devices=${input.devices}
|
||||
.registry=${input.registry} .currentSpace=${input.currentSpace} .spaceTitles=${spaceTitles}
|
||||
.registry=${input.registry} .currentSpace=${input.currentSpace} .spaces=${input.spaces}
|
||||
.viewKey=${input.viewKey}></hp-zigbee-topology-overlay>`;
|
||||
}
|
||||
|
||||
+4
-12
@@ -107,20 +107,12 @@ function lqiOf(value: unknown): number | undefined {
|
||||
return Number.isFinite(n) && n >= 0 && n <= 255 ? Math.round(n) : undefined;
|
||||
}
|
||||
|
||||
const Z2M_RELATIONSHIPS: Readonly<Record<number, string>> = {
|
||||
0: 'parent', 1: 'child', 2: 'sibling', 3: 'none', 4: 'previous_child',
|
||||
};
|
||||
const Z2M_RELATIONSHIPS = ['parent', 'child', 'sibling', 'none', 'previous_child'] as const;
|
||||
|
||||
function relationshipOf(value: unknown): string | undefined {
|
||||
if (typeof value === 'number' && Number.isInteger(value)) return Z2M_RELATIONSHIPS[value];
|
||||
if (typeof value !== 'string') return undefined;
|
||||
const compact = value.trim().toLowerCase().replace(/[\s_-]+/g, '');
|
||||
if (!compact) return undefined;
|
||||
if (compact === 'previouschild') return 'previous_child';
|
||||
if (compact === 'parent' || compact === 'child' || compact === 'sibling' || compact === 'none') {
|
||||
return compact;
|
||||
}
|
||||
return value.trim().toLowerCase().slice(0, 40) || undefined;
|
||||
if (typeof value === 'number') return Z2M_RELATIONSHIPS[value];
|
||||
return typeof value === 'string'
|
||||
? value.trim().toLowerCase().slice(0, 40) || undefined : undefined;
|
||||
}
|
||||
|
||||
function observation(value: unknown): ZigbeeDirectionalObservation {
|
||||
|
||||
Reference in New Issue
Block a user