diff --git a/src/mixins/subscribe-mixin.ts b/src/mixins/subscribe-mixin.ts index a4d877a85f..3250093763 100644 --- a/src/mixins/subscribe-mixin.ts +++ b/src/mixins/subscribe-mixin.ts @@ -12,7 +12,7 @@ export const SubscribeMixin = >( class SubscribeClass extends superClass { @property() public hass?: HomeAssistant; - private __unsubs?: UnsubscribeFunc[]; + private __unsubs?: Array>; public connectedCallback() { super.connectedCallback(); @@ -23,7 +23,8 @@ export const SubscribeMixin = >( super.disconnectedCallback(); if (this.__unsubs) { while (this.__unsubs.length) { - this.__unsubs.pop()!(); + const unsub = this.__unsubs.pop()!; + Promise.resolve(unsub).then((unsubFunc) => unsubFunc()); } this.__unsubs = undefined; } @@ -36,7 +37,9 @@ export const SubscribeMixin = >( } } - protected hassSubscribe(): UnsubscribeFunc[] { + protected hassSubscribe(): Array< + UnsubscribeFunc | Promise + > { return []; } diff --git a/src/panels/lovelace/cards/hui-markdown-card.ts b/src/panels/lovelace/cards/hui-markdown-card.ts index 475531c578..ef0f9fe1ee 100644 --- a/src/panels/lovelace/cards/hui-markdown-card.ts +++ b/src/panels/lovelace/cards/hui-markdown-card.ts @@ -41,7 +41,7 @@ export class HuiMarkdownCard extends LitElement implements LovelaceCard { @property() private _content = ""; - @property() private _unsubRenderTemplate?: UnsubscribeFunc; + @property() private _unsubRenderTemplate?: Promise; public getCardSize(): number { return this._config === undefined @@ -122,7 +122,7 @@ export class HuiMarkdownCard extends LitElement implements LovelaceCard { } try { - this._unsubRenderTemplate = await subscribeRenderTemplate( + this._unsubRenderTemplate = subscribeRenderTemplate( this.hass.connection, (result) => { this._content = result; @@ -148,7 +148,8 @@ export class HuiMarkdownCard extends LitElement implements LovelaceCard { } try { - this._unsubRenderTemplate(); + const unsub = await this._unsubRenderTemplate; + unsub(); this._unsubRenderTemplate = undefined; } catch (e) { if (e.code === "not_found") { diff --git a/src/panels/lovelace/cards/hui-shopping-list-card.ts b/src/panels/lovelace/cards/hui-shopping-list-card.ts index 2695f7fcf2..85395dfffd 100644 --- a/src/panels/lovelace/cards/hui-shopping-list-card.ts +++ b/src/panels/lovelace/cards/hui-shopping-list-card.ts @@ -25,9 +25,12 @@ import { import { HomeAssistant } from "../../../types"; import { LovelaceCard, LovelaceCardEditor } from "../types"; import { SensorCardConfig, ShoppingListCardConfig } from "./types"; +import { SubscribeMixin } from "../../../mixins/subscribe-mixin"; +import { UnsubscribeFunc } from "home-assistant-js-websocket"; @customElement("hui-shopping-list-card") -class HuiShoppingListCard extends LitElement implements LovelaceCard { +class HuiShoppingListCard extends SubscribeMixin(LitElement) + implements LovelaceCard { public static async getConfigElement(): Promise { await import( /* webpackChunkName: "hui-shopping-list-editor" */ "../editor/config-elements/hui-shopping-list-editor" @@ -47,8 +50,6 @@ class HuiShoppingListCard extends LitElement implements LovelaceCard { @property() private _checkedItems?: ShoppingListItem[]; - private _unsubEvents?: Promise<() => Promise>; - public getCardSize(): number { return (this._config ? (this._config.title ? 1 : 0) : 0) + 3; } @@ -57,27 +58,16 @@ class HuiShoppingListCard extends LitElement implements LovelaceCard { this._config = config; this._uncheckedItems = []; this._checkedItems = []; - this._fetchData(); } - public connectedCallback(): void { - super.connectedCallback(); - - if (this.hass) { - this._unsubEvents = this.hass.connection.subscribeEvents( + public hassSubscribe(): Promise[] { + this._fetchData(); + return [ + this.hass!.connection.subscribeEvents( () => this._fetchData(), "shopping_list_updated" - ); - this._fetchData(); - } - } - - public disconnectedCallback(): void { - super.disconnectedCallback(); - - if (this._unsubEvents) { - this._unsubEvents.then((unsub) => unsub()); - } + ), + ]; } protected updated(changedProps: PropertyValues): void { @@ -85,16 +75,15 @@ class HuiShoppingListCard extends LitElement implements LovelaceCard { if (!this._config || !this.hass) { return; } + const oldHass = changedProps.get("hass") as HomeAssistant | undefined; const oldConfig = changedProps.get("_config") as | SensorCardConfig | undefined; if ( - !oldHass || - !oldConfig || - oldHass.themes !== this.hass.themes || - oldConfig.theme !== this._config.theme + (changedProps.has("hass") && oldHass?.themes !== this.hass.themes) || + (changedProps.has("_config") && oldConfig?.theme !== this._config.theme) ) { applyThemesOnElement(this, this.hass.themes, this._config.theme); } @@ -199,6 +188,67 @@ class HuiShoppingListCard extends LitElement implements LovelaceCard { `; } + private async _fetchData(): Promise { + if (!this.hass) { + return; + } + const checkedItems: ShoppingListItem[] = []; + const uncheckedItems: ShoppingListItem[] = []; + const items = await fetchItems(this.hass); + for (const key in items) { + if (items[key].complete) { + checkedItems.push(items[key]); + } else { + uncheckedItems.push(items[key]); + } + } + this._checkedItems = checkedItems; + this._uncheckedItems = uncheckedItems; + } + + private _completeItem(ev): void { + updateItem(this.hass!, ev.target.itemId, { + complete: ev.target.checked, + }).catch(() => this._fetchData()); + } + + private _saveEdit(ev): void { + updateItem(this.hass!, ev.target.itemId, { + name: ev.target.value, + }).catch(() => this._fetchData()); + + ev.target.blur(); + } + + private _clearItems(): void { + if (this.hass) { + clearItems(this.hass).catch(() => this._fetchData()); + } + } + + private get _newItem(): PaperInputElement { + return this.shadowRoot!.querySelector(".addBox") as PaperInputElement; + } + + private _addItem(ev): void { + const newItem = this._newItem; + + if (newItem.value!.length > 0) { + addItem(this.hass!, newItem.value!).catch(() => this._fetchData()); + } + + newItem.value = ""; + if (ev) { + newItem.focus(); + } + } + + private _addKeyPress(ev): void { + if (ev.keyCode === 13) { + this._addItem(null); + } + } + static get styles(): CSSResult { return css` ha-card { @@ -257,66 +307,6 @@ class HuiShoppingListCard extends LitElement implements LovelaceCard { } `; } - - private async _fetchData(): Promise { - if (this.hass) { - const checkedItems: ShoppingListItem[] = []; - const uncheckedItems: ShoppingListItem[] = []; - const items = await fetchItems(this.hass); - for (const key in items) { - if (items[key].complete) { - checkedItems.push(items[key]); - } else { - uncheckedItems.push(items[key]); - } - } - this._checkedItems = checkedItems; - this._uncheckedItems = uncheckedItems; - } - } - - private _completeItem(ev): void { - updateItem(this.hass!, ev.target.itemId, { - complete: ev.target.checked, - }).catch(() => this._fetchData()); - } - - private _saveEdit(ev): void { - updateItem(this.hass!, ev.target.itemId, { - name: ev.target.value, - }).catch(() => this._fetchData()); - - ev.target.blur(); - } - - private _clearItems(): void { - if (this.hass) { - clearItems(this.hass).catch(() => this._fetchData()); - } - } - - private get _newItem(): PaperInputElement { - return this.shadowRoot!.querySelector(".addBox") as PaperInputElement; - } - - private _addItem(ev): void { - const newItem = this._newItem; - - if (newItem.value!.length > 0) { - addItem(this.hass!, newItem.value!).catch(() => this._fetchData()); - } - - newItem.value = ""; - if (ev) { - newItem.focus(); - } - } - - private _addKeyPress(ev): void { - if (ev.keyCode === 13) { - this._addItem(null); - } - } } declare global {