Use subscribe for todo items (#18776)

This commit is contained in:
Bram Kragten 2023-11-28 08:28:13 +01:00 committed by GitHub
parent db68c7faa9
commit ffb19b31a5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 47 additions and 56 deletions

View File

@ -47,15 +47,25 @@ export interface TodoItems {
export const fetchItems = async (
hass: HomeAssistant,
entityId: string
entity_id: string
): Promise<TodoItem[]> => {
const result = await hass.callWS<TodoItems>({
type: "todo/item/list",
entity_id: entityId,
entity_id,
});
return result.items;
};
export const subscribeItems = (
hass: HomeAssistant,
entity_id: string,
callback: (item) => void
) =>
hass.connection.subscribeMessage<any>(callback, {
type: "todo/item/subscribe",
entity_id,
});
export const updateItem = (
hass: HomeAssistant,
entity_id: string,

View File

@ -24,36 +24,32 @@ import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_elemen
import { supportsFeature } from "../../../common/entity/supports-feature";
import "../../../components/ha-card";
import "../../../components/ha-checkbox";
import "../../../components/ha-icon-button";
import "../../../components/ha-list-item";
import "../../../components/ha-select";
import "../../../components/ha-svg-icon";
import "../../../components/ha-icon-button";
import "../../../components/ha-textfield";
import type { HaTextField } from "../../../components/ha-textfield";
import { isUnavailableState } from "../../../data/entity";
import {
TodoItem,
TodoItemStatus,
TodoListEntityFeature,
createItem,
deleteItems,
fetchItems,
moveItem,
subscribeItems,
updateItem,
} from "../../../data/todo";
import { SubscribeMixin } from "../../../mixins/subscribe-mixin";
import type { SortableInstance } from "../../../resources/sortable";
import { HomeAssistant } from "../../../types";
import { findEntities } from "../common/find-entities";
import { createEntityNotFoundWarning } from "../components/hui-warning";
import { LovelaceCard, LovelaceCardEditor } from "../types";
import { TodoListCardConfig } from "./types";
import { isUnavailableState } from "../../../data/entity";
@customElement("hui-todo-list-card")
export class HuiTodoListCard
extends SubscribeMixin(LitElement)
implements LovelaceCard
{
export class HuiTodoListCard extends LitElement implements LovelaceCard {
public static async getConfigElement(): Promise<LovelaceCardEditor> {
await import("../editor/config-elements/hui-todo-list-editor");
return document.createElement("hui-todo-list-card-editor");
@ -87,10 +83,24 @@ export class HuiTodoListCard
@state() private _reordering = false;
private _unsubItems?: Promise<UnsubscribeFunc>;
private _sortable?: SortableInstance;
@query("#unchecked") private _uncheckedContainer?: HTMLElement;
connectedCallback(): void {
super.connectedCallback();
if (this.hasUpdated) {
this._subscribeItems();
}
}
disconnectedCallback(): void {
super.disconnectedCallback();
this._unsubItems?.then((unsub) => unsub());
}
public getCardSize(): number {
return (this._config ? (this._config.title ? 2 : 0) : 0) + 3;
}
@ -132,26 +142,13 @@ export class HuiTodoListCard
if (!this._entityId) {
this._entityId = this.getEntityId();
}
this._fetchData();
this._subscribeItems();
} else if (changedProperties.has("_entityId") || !this._items) {
this._items = undefined;
this._fetchData();
this._subscribeItems();
}
}
public hassSubscribe(): Promise<UnsubscribeFunc>[] {
return [
this.hass!.connection.subscribeEvents(() => {
if (
this._entityId &&
this.hass!.entities[this._entityId]?.platform === "shopping_list"
) {
this._fetchData();
}
}, "shopping_list_updated"),
];
}
protected updated(changedProps: PropertyValues): void {
super.updated(changedProps);
if (!this._config || !this.hass) {
@ -169,15 +166,6 @@ export class HuiTodoListCard
) {
applyThemesOnElement(this, this.hass.themes, this._config.theme);
}
if (
this._entityId &&
oldHass &&
oldHass.states[this._entityId] !== this.hass.states[this._entityId] &&
this.hass.entities[this._entityId]?.platform !== "shopping_list"
) {
this._fetchData();
}
}
protected render() {
@ -392,14 +380,20 @@ export class HuiTodoListCard
return entityStateObj && supportsFeature(entityStateObj, feature);
}
private async _fetchData(): Promise<void> {
private async _subscribeItems(): Promise<void> {
if (this._unsubItems) {
this._unsubItems.then((unsub) => unsub());
this._unsubItems = undefined;
}
if (!this.hass || !this._entityId) {
return;
}
if (!(this._entityId in this.hass.states)) {
return;
}
this._items = await fetchItems(this.hass!, this._entityId!);
this._unsubItems = subscribeItems(this.hass!, this._entityId, (update) => {
this._items = update.items;
});
}
private _getItem(itemId: string) {
@ -416,7 +410,7 @@ export class HuiTodoListCard
status: ev.target.checked
? TodoItemStatus.Completed
: TodoItemStatus.NeedsAction,
}).finally(() => this._fetchData());
});
}
private _saveEdit(ev): void {
@ -429,13 +423,11 @@ export class HuiTodoListCard
updateItem(this.hass!, this._entityId!, {
...item,
summary: ev.target.value,
}).finally(() => this._fetchData());
});
} else if (
this.todoListSupportsFeature(TodoListEntityFeature.DELETE_TODO_ITEM)
) {
deleteItems(this.hass!, this._entityId!, [ev.target.itemId]).finally(() =>
this._fetchData()
);
deleteItems(this.hass!, this._entityId!, [ev.target.itemId]);
}
ev.target.blur();
@ -447,9 +439,7 @@ export class HuiTodoListCard
}
const checkedItems = this._getCheckedItems(this._items);
const uids = checkedItems.map((item: TodoItem) => item.uid);
deleteItems(this.hass!, this._entityId!, uids).finally(() =>
this._fetchData()
);
deleteItems(this.hass!, this._entityId!, uids);
}
private get _newItem(): HaTextField {
@ -459,9 +449,7 @@ export class HuiTodoListCard
private _addItem(ev): void {
const newItem = this._newItem;
if (newItem.value!.length > 0) {
createItem(this.hass!, this._entityId!, newItem.value!).finally(() =>
this._fetchData()
);
createItem(this.hass!, this._entityId!, newItem.value!);
}
newItem.value = "";
@ -475,9 +463,7 @@ export class HuiTodoListCard
if (!item) {
return;
}
deleteItems(this.hass!, this._entityId!, [item.uid]).finally(() =>
this._fetchData()
);
deleteItems(this.hass!, this._entityId!, [item.uid]);
}
private _addKeyPress(ev): void {
@ -552,12 +538,7 @@ export class HuiTodoListCard
}
this._items = [...this._items!];
await moveItem(
this.hass!,
this._entityId!,
item.uid,
prevItem?.uid
).finally(() => this._fetchData());
await moveItem(this.hass!, this._entityId!, item.uid, prevItem?.uid);
}
static get styles(): CSSResultGroup {