diff --git a/src/components/ha-area-floor-picker.ts b/src/components/ha-area-floor-picker.ts index 12a032bdecf4..a9fe503f10cf 100644 --- a/src/components/ha-area-floor-picker.ts +++ b/src/components/ha-area-floor-picker.ts @@ -1,6 +1,6 @@ import { mdiTextureBox } from "@mdi/js"; import { ComboBoxLitRenderer } from "@vaadin/combo-box/lit"; -import { HassEntity, UnsubscribeFunc } from "home-assistant-js-websocket"; +import { HassEntity } from "home-assistant-js-websocket"; import { LitElement, PropertyValues, TemplateResult, html, nothing } from "lit"; import { customElement, property, query, state } from "lit/decorators"; import { styleMap } from "lit/directives/style-map"; @@ -20,12 +20,7 @@ import { getDeviceEntityDisplayLookup, } from "../data/device_registry"; import { EntityRegistryDisplayEntry } from "../data/entity_registry"; -import { - FloorRegistryEntry, - getFloorAreaLookup, - subscribeFloorRegistry, -} from "../data/floor_registry"; -import { SubscribeMixin } from "../mixins/subscribe-mixin"; +import { FloorRegistryEntry, getFloorAreaLookup } from "../data/floor_registry"; import { HomeAssistant, ValueChangedEvent } from "../types"; import type { HaDevicePickerDeviceFilterFunc } from "./device/ha-device-picker"; import "./ha-combo-box"; @@ -50,7 +45,7 @@ interface FloorAreaEntry { } @customElement("ha-area-floor-picker") -export class HaAreaFloorPicker extends SubscribeMixin(LitElement) { +export class HaAreaFloorPicker extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; @property() public label?: string; @@ -111,22 +106,12 @@ export class HaAreaFloorPicker extends SubscribeMixin(LitElement) { @property({ type: Boolean }) public required = false; - @state() private _floors?: FloorRegistryEntry[]; - @state() private _opened?: boolean; @query("ha-combo-box", true) public comboBox!: HaComboBox; private _init = false; - protected hassSubscribe(): (UnsubscribeFunc | Promise)[] { - return [ - subscribeFloorRegistry(this.hass.connection, (floors) => { - this._floors = floors; - }), - ]; - } - public async open() { await this.updateComplete; await this.comboBox?.open(); @@ -431,12 +416,12 @@ export class HaAreaFloorPicker extends SubscribeMixin(LitElement) { protected updated(changedProps: PropertyValues) { if ( - (!this._init && this.hass && this._floors) || + (!this._init && this.hass) || (this._init && changedProps.has("_opened") && this._opened) ) { this._init = true; const areas = this._getAreas( - this._floors!, + Object.values(this.hass.floors), Object.values(this.hass.areas), Object.values(this.hass.devices), Object.values(this.hass.entities), diff --git a/src/components/ha-filter-floor-areas.ts b/src/components/ha-filter-floor-areas.ts index 921e5c49fe52..6585a10af31a 100644 --- a/src/components/ha-filter-floor-areas.ts +++ b/src/components/ha-filter-floor-areas.ts @@ -1,6 +1,5 @@ import "@material/mwc-menu/mwc-menu-surface"; import { mdiFilterVariantRemove, mdiTextureBox } from "@mdi/js"; -import { UnsubscribeFunc } from "home-assistant-js-websocket"; import { CSSResultGroup, LitElement, @@ -15,13 +14,8 @@ import { repeat } from "lit/directives/repeat"; import memoizeOne from "memoize-one"; import { fireEvent } from "../common/dom/fire_event"; import { computeRTL } from "../common/util/compute_rtl"; -import { - FloorRegistryEntry, - getFloorAreaLookup, - subscribeFloorRegistry, -} from "../data/floor_registry"; +import { getFloorAreaLookup } from "../data/floor_registry"; import { RelatedResult, findRelated } from "../data/search"; -import { SubscribeMixin } from "../mixins/subscribe-mixin"; import { haStyleScrollbar } from "../resources/styles"; import type { HomeAssistant } from "../types"; import "./ha-check-list-item"; @@ -31,7 +25,7 @@ import "./ha-svg-icon"; import "./ha-tree-indicator"; @customElement("ha-filter-floor-areas") -export class HaFilterFloorAreas extends SubscribeMixin(LitElement) { +export class HaFilterFloorAreas extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; @property({ attribute: false }) public value?: { @@ -47,8 +41,6 @@ export class HaFilterFloorAreas extends SubscribeMixin(LitElement) { @state() private _shouldRender = false; - @state() private _floors?: FloorRegistryEntry[]; - public willUpdate(properties: PropertyValues) { super.willUpdate(properties); @@ -60,7 +52,7 @@ export class HaFilterFloorAreas extends SubscribeMixin(LitElement) { } protected render() { - const areas = this._areas(this.hass.areas, this._floors); + const areas = this._areas(this.hass.areas, this.hass.floors); return html` )[] { - return [ - subscribeFloorRegistry(this.hass.connection, (floors) => { - this._floors = floors; - }), - ]; - } - protected updated(changed) { if (changed.has("expanded") && this.expanded) { setTimeout(() => { @@ -220,9 +204,9 @@ export class HaFilterFloorAreas extends SubscribeMixin(LitElement) { } private _areas = memoizeOne( - (areaReg: HomeAssistant["areas"], floors?: FloorRegistryEntry[]) => { + (areaReg: HomeAssistant["areas"], floorReg: HomeAssistant["floors"]) => { const areas = Object.values(areaReg); - + const floors = Object.values(floorReg); const floorAreaLookup = getFloorAreaLookup(areas); const unassisgnedAreas = areas.filter( diff --git a/src/components/ha-floor-picker.ts b/src/components/ha-floor-picker.ts index d790ec1a4603..17a958936e15 100644 --- a/src/components/ha-floor-picker.ts +++ b/src/components/ha-floor-picker.ts @@ -1,5 +1,5 @@ import { ComboBoxLitRenderer } from "@vaadin/combo-box/lit"; -import { HassEntity, UnsubscribeFunc } from "home-assistant-js-websocket"; +import { HassEntity } from "home-assistant-js-websocket"; import { LitElement, PropertyValues, TemplateResult, html } from "lit"; import { customElement, property, query, state } from "lit/decorators"; import { classMap } from "lit/directives/class-map"; @@ -24,10 +24,8 @@ import { FloorRegistryEntry, createFloorRegistryEntry, getFloorAreaLookup, - subscribeFloorRegistry, } from "../data/floor_registry"; import { showAlertDialog } from "../dialogs/generic/show-dialog-box"; -import { SubscribeMixin } from "../mixins/subscribe-mixin"; import { showFloorRegistryDetailDialog } from "../panels/config/areas/show-dialog-floor-registry-detail"; import { HomeAssistant, ValueChangedEvent } from "../types"; import type { HaDevicePickerDeviceFilterFunc } from "./device/ha-device-picker"; @@ -53,7 +51,7 @@ const rowRenderer: ComboBoxLitRenderer = (item) => `; @customElement("ha-floor-picker") -export class HaFloorPicker extends SubscribeMixin(LitElement) { +export class HaFloorPicker extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; @property() public label?: string; @@ -111,8 +109,6 @@ export class HaFloorPicker extends SubscribeMixin(LitElement) { @state() private _opened?: boolean; - @state() private _floors?: FloorRegistryEntry[]; - @query("ha-combo-box", true) public comboBox!: HaComboBox; private _suggestion?: string; @@ -129,14 +125,6 @@ export class HaFloorPicker extends SubscribeMixin(LitElement) { await this.comboBox?.focus(); } - protected hassSubscribe(): (UnsubscribeFunc | Promise)[] { - return [ - subscribeFloorRegistry(this.hass.connection, (floors) => { - this._floors = floors; - }), - ]; - } - private _getFloors = memoizeOne( ( floors: FloorRegistryEntry[], @@ -320,12 +308,12 @@ export class HaFloorPicker extends SubscribeMixin(LitElement) { protected updated(changedProps: PropertyValues) { if ( - (!this._init && this.hass && this._floors) || + (!this._init && this.hass) || (this._init && changedProps.has("_opened") && this._opened) ) { this._init = true; const floors = this._getFloors( - this._floors!, + Object.values(this.hass.floors), Object.values(this.hass.areas), Object.values(this.hass.devices), Object.values(this.hass.entities), @@ -360,8 +348,7 @@ export class HaFloorPicker extends SubscribeMixin(LitElement) { ? this.hass.localize("ui.components.floor-picker.floor") : this.label} .placeholder=${this.placeholder - ? this._floors?.find((floor) => floor.floor_id === this.placeholder) - ?.name + ? this.hass.floors[this.placeholder]?.name : undefined} .renderer=${rowRenderer} @filter-changed=${this._filterChanged} @@ -460,7 +447,7 @@ export class HaFloorPicker extends SubscribeMixin(LitElement) { floor_id: floor.floor_id, }); }); - const floors = [...this._floors!, floor]; + const floors = [...Object.values(this.hass.floors), floor]; this.comboBox.filteredItems = this._getFloors( floors, Object.values(this.hass.areas)!, diff --git a/src/components/ha-target-picker.ts b/src/components/ha-target-picker.ts index c20a465e442e..527de786acd9 100644 --- a/src/components/ha-target-picker.ts +++ b/src/components/ha-target-picker.ts @@ -35,10 +35,6 @@ import { computeDeviceName, } from "../data/device_registry"; import { EntityRegistryDisplayEntry } from "../data/entity_registry"; -import { - FloorRegistryEntry, - subscribeFloorRegistry, -} from "../data/floor_registry"; import { LabelRegistryEntry, subscribeLabelRegistry, @@ -103,17 +99,12 @@ export class HaTargetPicker extends SubscribeMixin(LitElement) { @query(".add-container", true) private _addContainer?: HTMLDivElement; - @state() private _floors?: FloorRegistryEntry[]; - @state() private _labels?: LabelRegistryEntry[]; private _opened = false; protected hassSubscribe(): (UnsubscribeFunc | Promise)[] { return [ - subscribeFloorRegistry(this.hass.connection, (floors) => { - this._floors = floors; - }), subscribeLabelRegistry(this.hass.connection, (labels) => { this._labels = labels; }), @@ -132,9 +123,7 @@ export class HaTargetPicker extends SubscribeMixin(LitElement) {
${this.value?.floor_id ? ensureArray(this.value.floor_id).map((floor_id) => { - const floor = this._floors?.find( - (flr) => flr.floor_id === floor_id - ); + const floor = this.hass.floors[floor_id]; return this._renderChip( "floor_id", floor_id, diff --git a/src/data/floor_registry.ts b/src/data/floor_registry.ts index 1a31cbf09b11..d6b657661b1d 100644 --- a/src/data/floor_registry.ts +++ b/src/data/floor_registry.ts @@ -1,7 +1,4 @@ -import { Connection, createCollection } from "home-assistant-js-websocket"; -import { Store } from "home-assistant-js-websocket/dist/store"; import { stringCompare } from "../common/string/compare"; -import { debounce } from "../common/util/debounce"; import { HomeAssistant } from "../types"; import { AreaRegistryEntry } from "./area_registry"; import { RegistryEntry } from "./registry"; @@ -27,48 +24,6 @@ export interface FloorRegistryEntryMutableParams { aliases?: string[]; } -const fetchFloorRegistry = (conn: Connection) => - conn - .sendMessagePromise({ - type: "config/floor_registry/list", - }) - .then((floors) => - (floors as FloorRegistryEntry[]).sort((ent1, ent2) => { - if (ent1.level !== ent2.level) { - return (ent1.level ?? 9999) - (ent2.level ?? 9999); - } - return stringCompare(ent1.name, ent2.name); - }) - ); - -const subscribeFloorRegistryUpdates = ( - conn: Connection, - store: Store -) => - conn.subscribeEvents( - debounce( - () => - fetchFloorRegistry(conn).then((areas: FloorRegistryEntry[]) => - store.setState(areas, true) - ), - 500, - true - ), - "floor_registry_updated" - ); - -export const subscribeFloorRegistry = ( - conn: Connection, - onChange: (floors: FloorRegistryEntry[]) => void -) => - createCollection( - "_floorRegistry", - fetchFloorRegistry, - subscribeFloorRegistryUpdates, - conn, - onChange - ); - export const createFloorRegistryEntry = ( hass: HomeAssistant, values: FloorRegistryEntryMutableParams diff --git a/src/data/ws-floor_registry.ts b/src/data/ws-floor_registry.ts new file mode 100644 index 000000000000..be9da56e90ae --- /dev/null +++ b/src/data/ws-floor_registry.ts @@ -0,0 +1,47 @@ +import { Connection, createCollection } from "home-assistant-js-websocket"; +import { Store } from "home-assistant-js-websocket/dist/store"; +import { stringCompare } from "../common/string/compare"; +import { debounce } from "../common/util/debounce"; +import { FloorRegistryEntry } from "./floor_registry"; + +const fetchFloorRegistry = (conn: Connection) => + conn + .sendMessagePromise({ + type: "config/floor_registry/list", + }) + .then((floors) => + (floors as FloorRegistryEntry[]).sort((ent1, ent2) => { + if (ent1.level !== ent2.level) { + return (ent1.level ?? 9999) - (ent2.level ?? 9999); + } + return stringCompare(ent1.name, ent2.name); + }) + ); + +const subscribeFloorRegistryUpdates = ( + conn: Connection, + store: Store +) => + conn.subscribeEvents( + debounce( + () => + fetchFloorRegistry(conn).then((areas: FloorRegistryEntry[]) => + store.setState(areas, true) + ), + 500, + true + ), + "floor_registry_updated" + ); + +export const subscribeFloorRegistry = ( + conn: Connection, + onChange: (floors: FloorRegistryEntry[]) => void +) => + createCollection( + "_floorRegistry", + fetchFloorRegistry, + subscribeFloorRegistryUpdates, + conn, + onChange + ); diff --git a/src/entrypoints/core.ts b/src/entrypoints/core.ts index c0b83b90cc7a..7ddc8aa245bd 100644 --- a/src/entrypoints/core.ts +++ b/src/entrypoints/core.ts @@ -21,6 +21,7 @@ import { subscribeRepairsIssueRegistry } from "../data/repairs"; import { subscribeAreaRegistry } from "../data/ws-area_registry"; import { subscribeDeviceRegistry } from "../data/ws-device_registry"; import { subscribeEntityRegistryDisplay } from "../data/ws-entity_registry_display"; +import { subscribeFloorRegistry } from "../data/ws-floor_registry"; import { subscribePanels } from "../data/ws-panels"; import { subscribeThemes } from "../data/ws-themes"; import { subscribeUser } from "../data/ws-user"; @@ -117,6 +118,7 @@ window.hassConnection.then(({ conn }) => { subscribeEntityRegistryDisplay(conn, noop); subscribeDeviceRegistry(conn, noop); subscribeAreaRegistry(conn, noop); + subscribeFloorRegistry(conn, noop); subscribeConfig(conn, noop); subscribeServices(conn, noop); subscribePanels(conn, noop); diff --git a/src/panels/config/areas/ha-config-areas-dashboard.ts b/src/panels/config/areas/ha-config-areas-dashboard.ts index b63be2f40906..5892abde3a3b 100644 --- a/src/panels/config/areas/ha-config-areas-dashboard.ts +++ b/src/panels/config/areas/ha-config-areas-dashboard.ts @@ -6,7 +6,6 @@ import { mdiPencil, mdiPlus, } from "@mdi/js"; -import { UnsubscribeFunc } from "home-assistant-js-websocket"; import { CSSResultGroup, LitElement, @@ -15,15 +14,15 @@ import { html, nothing, } from "lit"; -import { customElement, property, state } from "lit/decorators"; +import { customElement, property } from "lit/decorators"; import { styleMap } from "lit/directives/style-map"; import memoizeOne from "memoize-one"; import { formatListWithAnds } from "../../../common/string/format-list"; import "../../../components/ha-fab"; import "../../../components/ha-floor-icon"; import "../../../components/ha-icon-button"; -import "../../../components/ha-svg-icon"; import "../../../components/ha-sortable"; +import "../../../components/ha-svg-icon"; import { AreaRegistryEntry, createAreaRegistryEntry, @@ -34,7 +33,6 @@ import { createFloorRegistryEntry, deleteFloorRegistryEntry, getFloorAreaLookup, - subscribeFloorRegistry, updateFloorRegistryEntry, } from "../../../data/floor_registry"; import { @@ -42,7 +40,6 @@ import { showConfirmationDialog, } from "../../../dialogs/generic/show-dialog-box"; import "../../../layouts/hass-tabs-subpage"; -import { SubscribeMixin } from "../../../mixins/subscribe-mixin"; import { HomeAssistant, Route } from "../../../types"; import "../ha-config-section"; import { configSections } from "../ha-panel-config"; @@ -57,7 +54,7 @@ const UNASSIGNED_PATH = ["__unassigned__"]; const SORT_OPTIONS = { sort: false, delay: 500, delayOnTouchOnly: true }; @customElement("ha-config-areas-dashboard") -export class HaConfigAreasDashboard extends SubscribeMixin(LitElement) { +export class HaConfigAreasDashboard extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; @property({ type: Boolean }) public isWide = false; @@ -66,14 +63,12 @@ export class HaConfigAreasDashboard extends SubscribeMixin(LitElement) { @property({ attribute: false }) public route!: Route; - @state() private _floors?: FloorRegistryEntry[]; - private _processAreas = memoizeOne( ( areas: HomeAssistant["areas"], devices: HomeAssistant["devices"], entities: HomeAssistant["entities"], - floors: FloorRegistryEntry[] + floors: HomeAssistant["floors"] ) => { const processArea = (area: AreaRegistryEntry) => { let noDevicesInArea = 0; @@ -109,7 +104,7 @@ export class HaConfigAreasDashboard extends SubscribeMixin(LitElement) { (area) => !area.floor_id || !floorAreaLookup[area.floor_id] ); return { - floors: floors.map((floor) => ({ + floors: Object.values(floors).map((floor) => ({ ...floor, areas: (floorAreaLookup[floor.floor_id] || []).map(processArea), })), @@ -118,26 +113,18 @@ export class HaConfigAreasDashboard extends SubscribeMixin(LitElement) { } ); - protected hassSubscribe(): (UnsubscribeFunc | Promise)[] { - return [ - subscribeFloorRegistry(this.hass.connection, (floors) => { - this._floors = floors; - }), - ]; - } - protected render(): TemplateResult { const areasAndFloors = !this.hass.areas || !this.hass.devices || !this.hass.entities || - !this._floors + !this.hass.floors ? undefined : this._processAreas( this.hass.areas, this.hass.devices, this.hass.entities, - this._floors + this.hass.floors ); return html` @@ -327,7 +314,7 @@ export class HaConfigAreasDashboard extends SubscribeMixin(LitElement) { this.hass.areas, this.hass.devices, this.hass.entities, - this._floors! + this.hass.floors ); let area: AreaRegistryEntry; if (ev.detail.oldPath === UNASSIGNED_PATH) { diff --git a/src/panels/config/ha-panel-config.ts b/src/panels/config/ha-panel-config.ts index fe3151b2603d..8bdfcd042494 100644 --- a/src/panels/config/ha-panel-config.ts +++ b/src/panels/config/ha-panel-config.ts @@ -35,22 +35,17 @@ import { customElement, property, state } from "lit/decorators"; import { isComponentLoaded } from "../../common/config/is_component_loaded"; import { listenMediaQuery } from "../../common/dom/media_query"; import { CloudStatus, fetchCloudStatus } from "../../data/cloud"; -import { - floorsContext, - fullEntitiesContext, - labelsContext, -} from "../../data/context"; +import { fullEntitiesContext, labelsContext } from "../../data/context"; import { entityRegistryByEntityId, entityRegistryById, subscribeEntityRegistry, } from "../../data/entity_registry"; +import { subscribeLabelRegistry } from "../../data/label_registry"; import { HassRouterPage, RouterOptions } from "../../layouts/hass-router-page"; import { PageNavigation } from "../../layouts/hass-tabs-subpage"; import { SubscribeMixin } from "../../mixins/subscribe-mixin"; import { HomeAssistant, Route } from "../../types"; -import { subscribeLabelRegistry } from "../../data/label_registry"; -import { subscribeFloorRegistry } from "../../data/floor_registry"; declare global { // for fire event @@ -390,11 +385,6 @@ class HaPanelConfig extends SubscribeMixin(HassRouterPage) { initialValue: [], }); - private _floorsContext = new ContextProvider(this, { - context: floorsContext, - initialValue: [], - }); - public hassSubscribe(): UnsubscribeFunc[] { return [ subscribeEntityRegistry(this.hass.connection!, (entities) => { @@ -403,9 +393,6 @@ class HaPanelConfig extends SubscribeMixin(HassRouterPage) { subscribeLabelRegistry(this.hass.connection!, (labels) => { this._labelsContext.setValue(labels); }), - subscribeFloorRegistry(this.hass.connection!, (floors) => { - this._floorsContext.setValue(floors); - }), ]; } diff --git a/src/state/connection-mixin.ts b/src/state/connection-mixin.ts index 2f6525d4f71e..533532c57f58 100644 --- a/src/state/connection-mixin.ts +++ b/src/state/connection-mixin.ts @@ -34,6 +34,7 @@ import { getState } from "../util/ha-pref-storage"; import hassCallApi from "../util/hass-call-api"; import { HassBaseEl } from "./hass-base-mixin"; import { promiseTimeout } from "../common/util/promise-timeout"; +import { subscribeFloorRegistry } from "../data/ws-floor_registry"; export const connectionMixin = >( superClass: T @@ -52,6 +53,7 @@ export const connectionMixin = >( entities: null as any, devices: null as any, areas: null as any, + floors: null as any, config: null as any, themes: null as any, selectedTheme: null, @@ -266,6 +268,13 @@ export const connectionMixin = >( } this._updateHass({ areas }); }); + subscribeFloorRegistry(conn, (floorReg) => { + const floors: HomeAssistant["floors"] = {}; + for (const floor of floorReg) { + floors[floor.floor_id] = floor; + } + this._updateHass({ floors }); + }); subscribeConfig(conn, (config) => this._updateHass({ config })); subscribeServices(conn, (services) => this._updateHass({ services })); subscribePanels(conn, (panels) => this._updateHass({ panels })); diff --git a/src/types.ts b/src/types.ts index fb2a39618b59..d5d36f27e8a8 100644 --- a/src/types.ts +++ b/src/types.ts @@ -12,6 +12,7 @@ import { LocalizeFunc } from "./common/translations/localize"; import { AreaRegistryEntry } from "./data/area_registry"; import { DeviceRegistryEntry } from "./data/device_registry"; import { EntityRegistryDisplayEntry } from "./data/entity_registry"; +import { FloorRegistryEntry } from "./data/floor_registry"; import { CoreFrontendUserData } from "./data/frontend"; import { FrontendLocaleData, getHassTranslations } from "./data/translation"; import { Themes } from "./data/ws-themes"; @@ -210,6 +211,7 @@ export interface HomeAssistant { entities: { [id: string]: EntityRegistryDisplayEntry }; devices: { [id: string]: DeviceRegistryEntry }; areas: { [id: string]: AreaRegistryEntry }; + floors: { [id: string]: FloorRegistryEntry }; services: HassServices; config: HassConfig; themes: Themes;