From 16984d18bbe23a7ea2258a616d495d9c90942874 Mon Sep 17 00:00:00 2001 From: Donnie Date: Sat, 17 Oct 2020 15:48:48 -0700 Subject: [PATCH] Refactor quick bar to use a common interface for future commands and easier sorting (#7368) --- src/dialogs/quick-bar/ha-quick-bar.ts | 211 +++++++++----------------- 1 file changed, 70 insertions(+), 141 deletions(-) diff --git a/src/dialogs/quick-bar/ha-quick-bar.ts b/src/dialogs/quick-bar/ha-quick-bar.ts index 7036b8ce68..072e0e642f 100644 --- a/src/dialogs/quick-bar/ha-quick-bar.ts +++ b/src/dialogs/quick-bar/ha-quick-bar.ts @@ -15,7 +15,7 @@ import { import { fireEvent } from "../../common/dom/fire_event"; import "../../components/ha-dialog"; import { haStyleDialog } from "../../resources/styles"; -import { HomeAssistant, ServiceCallRequest } from "../../types"; +import { HomeAssistant } from "../../types"; import { PolymerChangedEvent } from "../../polymer-types"; import { fuzzySequentialMatch } from "../../common/string/sequence_matching"; import { componentsWithService } from "../../common/config/components_with_service"; @@ -23,21 +23,27 @@ import { domainIcon } from "../../common/entity/domain_icon"; import { computeDomain } from "../../common/entity/compute_domain"; import { domainToName } from "../../data/integration"; import { QuickBarParams } from "./show-dialog-quick-bar"; -import { HassEntity } from "home-assistant-js-websocket"; import { compare } from "../../common/string/compare"; import { SingleSelectedEvent } from "@material/mwc-list/mwc-list-foundation"; +import { computeStateName } from "../../common/entity/compute_state_name"; -interface CommandItem extends ServiceCallRequest { +interface QuickBarItem { text: string; + altText?: string; + icon: string; + action(data?: any): void; + score?: number; } @customElement("ha-quick-bar") export class QuickBar extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; - @internalProperty() private _commandItems: CommandItem[] = []; + @internalProperty() private _commandItems: QuickBarItem[] = []; - @internalProperty() private _entities: HassEntity[] = []; + @internalProperty() private _entityItems: QuickBarItem[] = []; + + @internalProperty() private _items: QuickBarItem[] = []; @internalProperty() private _itemFilter = ""; @@ -57,9 +63,7 @@ export class QuickBar extends LitElement { this._commandMode = params.commandMode || false; this._opened = true; this._commandItems = this._generateCommandItems(); - this._entities = Object.keys(this.hass.states).map( - (entity_id) => this.hass.states[entity_id] - ); + this._entityItems = this._generateEntityItems(); } public closeDialog() { @@ -91,84 +95,46 @@ export class QuickBar extends LitElement { @keydown=${this._handleInputKeyDown} @focus=${this._resetActivatedIndex} > - ${this._commandMode - ? this.renderCommandsList() - : this.renderEntityList()} + + ${this._items.map( + (item, index) => html` + + + ${item.text} + ${item.altText + ? html` ${item.altText} ` + : null} + ${this._commandTriggered === index + ? html`` + : null} + + ` + )} + `; } - protected renderCommandsList() { - const items = this._filterCommandItems( - this._commandItems, - this._itemFilter - ); + private async processItemAndCloseDialog(ev: SingleSelectedEvent) { + const index = ev.detail.index; + const item = (ev.target as any).items[index].item; - return html` - - ${items.map( - (item, index) => html` - - - ${item.text} - ${this._commandTriggered === index - ? html`` - : null} - - ` - )} - - `; - } + this._commandTriggered = index; - protected renderEntityList() { - const entities = this._filterEntityItems(this._itemFilter); - - return html` - - ${entities.map((entity, index) => { - const domain = computeDomain(entity.entity_id); - return html` - - - ${entity.attributes?.friendly_name - ? html` - - ${entity.attributes?.friendly_name} - - ${entity.entity_id} - ` - : html` - - ${entity.entity_id} - - `} - - `; - })} - - `; + await item.action(); + this.closeDialog(); } private _resetActivatedIndex() { @@ -213,9 +179,23 @@ export class QuickBar extends LitElement { this._commandMode = false; this._itemFilter = newFilter; } + + this._items = (this._commandMode ? this._commandItems : this._entityItems) + .filter(({ text, altText }) => { + const values = [text]; + if (altText) { + values.push(altText); + } + return fuzzySequentialMatch(this._itemFilter, values); + }) + .sort((itemA, itemB) => compare(itemA.text, itemB.text)); } - private _generateCommandItems(): CommandItem[] { + private _generateCommandItems(): QuickBarItem[] { + return [...this._generateReloadCommands()]; + } + + private _generateReloadCommands(): QuickBarItem[] { const reloadableDomains = componentsWithService(this.hass, "reload").sort(); return reloadableDomains.map((domain) => ({ @@ -226,69 +206,18 @@ export class QuickBar extends LitElement { "domain", domainToName(this.hass.localize, domain) ), - domain, - service: "reload", + icon: domainIcon(domain), + action: () => this.hass.callService(domain, "reload"), })); } - private _filterCommandItems( - items: CommandItem[], - filter: string - ): CommandItem[] { - return items - .filter(({ text }) => - fuzzySequentialMatch(filter.toLowerCase(), [text.toLowerCase()]) - ) - .sort((itemA, itemB) => compare(itemA.text, itemB.text)); - } - - private _filterEntityItems(filter: string): HassEntity[] { - return this._entities - .filter(({ entity_id, attributes: { friendly_name } }) => { - const values = [entity_id]; - if (friendly_name) { - values.push(friendly_name); - } - return fuzzySequentialMatch(filter.toLowerCase(), values); - }) - .sort((entityA, entityB) => - compare(entityA.entity_id, entityB.entity_id) - ); - } - - private async _processCommand(ev: SingleSelectedEvent) { - const index = ev.detail.index; - const item = (ev.target as any).items[index].item; - - this._commandTriggered = index; - - this._runCommandAndCloseDialog({ - domain: item.domain, - service: item.service, - serviceData: item.serviceData, - }); - } - - private async _runCommandAndCloseDialog(request?: ServiceCallRequest) { - if (!request) { - return; - } - - this.hass - .callService(request.domain, request.service, request.serviceData) - .then(() => this.closeDialog()); - } - - private _entityMoreInfo(ev: SingleSelectedEvent) { - const index = ev.detail.index; - const entityId = (ev.target as any).items[index].entityId; - - this._launchMoreInfoDialog(entityId); - } - - private _launchMoreInfoDialog(entityId) { - fireEvent(this, "hass-more-info", { entityId }); - this.closeDialog(); + private _generateEntityItems(): QuickBarItem[] { + return Object.keys(this.hass.states).map((entityId) => ({ + text: computeStateName(this.hass.states[entityId]), + altText: entityId, + icon: domainIcon(computeDomain(entityId), this.hass.states[entityId]), + action: () => fireEvent(this, "hass-more-info", { entityId }), + })); } static get styles() {