From 2e3193fc56c2242335fc118e3a9120f28f15412a Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Fri, 16 Oct 2020 15:42:34 +0200 Subject: [PATCH 01/11] Improve performance of quick bar --- src/common/search/search-input.ts | 10 +- src/dialogs/quick-bar/ha-quick-bar.ts | 200 +++++++++++++++++--------- 2 files changed, 136 insertions(+), 74 deletions(-) diff --git a/src/common/search/search-input.ts b/src/common/search/search-input.ts index 0b0038b9afe8..97a52b1864dc 100644 --- a/src/common/search/search-input.ts +++ b/src/common/search/search-input.ts @@ -51,18 +51,14 @@ class SearchInput extends LitElement { @value-changed=${this._filterInputChanged} .noLabelFloat=${this.noLabelFloat} > - + + + ${this.filter && html` diff --git a/src/dialogs/quick-bar/ha-quick-bar.ts b/src/dialogs/quick-bar/ha-quick-bar.ts index b7c099855ce8..c70c844351ff 100644 --- a/src/dialogs/quick-bar/ha-quick-bar.ts +++ b/src/dialogs/quick-bar/ha-quick-bar.ts @@ -1,6 +1,5 @@ import "../../components/ha-circular-progress"; import "../../components/ha-header-bar"; -import "@polymer/paper-input/paper-input"; import "@material/mwc-list/mwc-list-item"; import "@material/mwc-list/mwc-list"; import { @@ -10,17 +9,17 @@ import { internalProperty, LitElement, property, + PropertyValues, query, } from "lit-element"; import { fireEvent } from "../../common/dom/fire_event"; import "../../components/ha-dialog"; import { haStyleDialog } from "../../resources/styles"; -import { HomeAssistant } from "../../types"; -import { PolymerChangedEvent } from "../../polymer-types"; import { fuzzyFilterSort, ScorableTextItem, } from "../../common/string/filter/sequence-matching"; +import { HomeAssistant } from "../../types"; import { componentsWithService } from "../../common/config/components_with_service"; import { domainIcon } from "../../common/entity/domain_icon"; import { computeDomain } from "../../common/entity/compute_domain"; @@ -29,6 +28,11 @@ import { QuickBarParams } from "./show-dialog-quick-bar"; import { compare } from "../../common/string/compare"; import { SingleSelectedEvent } from "@material/mwc-list/mwc-list-foundation"; import { computeStateName } from "../../common/entity/compute_state_name"; +import memoizeOne from "memoize-one"; +import "../../common/search/search-input"; +import { mdiConsoleLine } from "@mdi/js"; +import { scroll } from "lit-virtualizer"; +import { styleMap } from "lit-html/directives/style-map"; interface QuickBarItem extends ScorableTextItem { icon: string; @@ -43,9 +47,9 @@ export class QuickBar extends LitElement { @internalProperty() private _entityItems: QuickBarItem[] = []; - @internalProperty() private _items: QuickBarItem[] = []; + @internalProperty() private _items?: QuickBarItem[] = []; - @internalProperty() private _itemFilter = ""; + @internalProperty() private _filter = ""; @internalProperty() private _opened = false; @@ -55,25 +59,37 @@ export class QuickBar extends LitElement { @internalProperty() private _activatedIndex = 0; - @query("paper-input", false) private _filterInputField?: HTMLElement; + @query("search-input", false) private _filterInputField?: HTMLElement; @query("mwc-list-item", false) private _firstListItem?: HTMLElement; public async showDialog(params: QuickBarParams) { this._commandMode = params.commandMode || false; - this._opened = true; this._commandItems = this._generateCommandItems(); this._entityItems = this._generateEntityItems(); + this._opened = true; } public closeDialog() { this._opened = false; - this._itemFilter = ""; + this._filter = ""; this._commandTriggered = -1; + this._items = []; this._resetActivatedIndex(); fireEvent(this, "dialog-closed", { dialog: this.localName }); } + protected updated(changedProperties: PropertyValues) { + if ( + this._opened && + (changedProperties.has("_opened") || + changedProperties.has("_filter") || + changedProperties.has("_commandMode")) + ) { + this._setFilteredItems(); + } + } + protected render() { if (!this._opened) { return html``; @@ -81,56 +97,78 @@ export class QuickBar extends LitElement { return html` - ${this._itemFilter}` : this._itemFilter} + .filter=${this._commandMode ? `>${this._filter}` : this._filter} @keydown=${this._handleInputKeyDown} @focus=${this._resetActivatedIndex} - > - - ${this._items.map( - (item, index) => html` - - - ${item.text} - ${item.altText - ? html` - ${item.altText} - ` - : null} - ${this._commandTriggered === index - ? html`` - : null} - - ` - )} - + > + ${this._commandMode + ? html`` + : ""} + + ${!this._items + ? html`` + : html` + ${scroll({ + items: this._items as [], + renderItem: (item: QuickBarItem, index?: number) => + this.renderItem(item, index), + })} + `} `; } + private renderItem(item: QuickBarItem, index?: number) { + return html` + + + ${item.text} + ${item.altText + ? html` + ${item.altText} + ` + : null} + ${this._commandTriggered === index + ? html`` + : null} + + `; + } + private async processItemAndCloseDialog(ev: SingleSelectedEvent) { const index = ev.detail.index; const item = (ev.target as any).items[index].item; @@ -154,6 +192,23 @@ export class QuickBar extends LitElement { } } + private _handleSearchChange(ev: CustomEvent): void { + const newFilter = ev.detail.value; + const oldCommandMode = this._commandMode; + + if (newFilter.startsWith(">")) { + this._commandMode = true; + this._filter = newFilter.substring(1); + } else { + this._commandMode = false; + this._filter = newFilter; + } + + if (oldCommandMode !== this._commandMode) { + this._items = undefined; + } + } + private _handleListItemKeyDown(ev: KeyboardEvent) { const isSingleCharacter = ev.key.length === 1; const isFirstListItem = (ev.target as any).index === 0; @@ -173,27 +228,6 @@ export class QuickBar extends LitElement { } } - private _entityFilterChanged(ev: PolymerChangedEvent) { - const newFilter = ev.detail.value; - - if (newFilter.startsWith(">")) { - this._commandMode = true; - this._itemFilter = newFilter.substring(1); - } else { - this._commandMode = false; - this._itemFilter = newFilter; - } - - this._items = this._commandMode ? this._commandItems : this._entityItems; - - if (this._itemFilter !== "") { - this._items = fuzzyFilterSort( - this._itemFilter.trimLeft(), - this._items - ); - } - } - private _generateCommandItems(): QuickBarItem[] { return [...this._generateReloadCommands()].sort((a, b) => compare(a.text.toLowerCase(), b.text.toLowerCase()) @@ -227,6 +261,18 @@ export class QuickBar extends LitElement { .sort((a, b) => compare(a.text.toLowerCase(), b.text.toLowerCase())); } + private async _setFilteredItems() { + this._items = this._commandMode ? this._commandItems : this._entityItems; + if (this._filter !== "") { + this._items = this._filterItems(this._items || [], this._filter); + } + } + + private _filterItems = memoizeOne( + (items: QuickBarItem[], filter: string): QuickBarItem[] => + fuzzyFilterSort(filter.trimLeft(), items) + ); + static get styles() { return [ haStyleDialog, @@ -242,7 +288,7 @@ export class QuickBar extends LitElement { ha-dialog { --dialog-z-index: 8; - --dialog-content-padding: 0px 24px 20px; + --dialog-content-padding: 0; } @media (min-width: 800px) { @@ -254,6 +300,26 @@ export class QuickBar extends LitElement { --mdc-dialog-max-height: calc(100% - 72px); } } + + ha-svg-icon.prefix { + margin: 8px; + } + + .uni-virtualizer-host { + display: block; + position: relative; + contain: strict; + overflow: auto; + height: 100%; + } + + .uni-virtualizer-host > * { + box-sizing: border-box; + } + + mwc-list-item { + width: 100%; + } `, ]; } From b04c6b116cb4d690f25f2438a411dfa6a094a5a8 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Fri, 16 Oct 2020 16:20:54 +0200 Subject: [PATCH 02/11] Fix keyboard nav --- src/dialogs/quick-bar/ha-quick-bar.ts | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/dialogs/quick-bar/ha-quick-bar.ts b/src/dialogs/quick-bar/ha-quick-bar.ts index c70c844351ff..2e06ca4720b2 100644 --- a/src/dialogs/quick-bar/ha-quick-bar.ts +++ b/src/dialogs/quick-bar/ha-quick-bar.ts @@ -26,7 +26,6 @@ import { computeDomain } from "../../common/entity/compute_domain"; import { domainToName } from "../../data/integration"; import { QuickBarParams } from "./show-dialog-quick-bar"; import { compare } from "../../common/string/compare"; -import { SingleSelectedEvent } from "@material/mwc-list/mwc-list-foundation"; import { computeStateName } from "../../common/entity/compute_state_name"; import memoizeOne from "memoize-one"; import "../../common/search/search-input"; @@ -61,7 +60,7 @@ export class QuickBar extends LitElement { @query("search-input", false) private _filterInputField?: HTMLElement; - @query("mwc-list-item", false) private _firstListItem?: HTMLElement; + @query("mwc-list", false) private _list?: HTMLElement; public async showDialog(params: QuickBarParams) { this._commandMode = params.commandMode || false; @@ -169,10 +168,7 @@ export class QuickBar extends LitElement { `; } - private async processItemAndCloseDialog(ev: SingleSelectedEvent) { - const index = ev.detail.index; - const item = (ev.target as any).items[index].item; - + private async processItemAndCloseDialog(item: QuickBarItem, index: number) { this._commandTriggered = index; await item.action(); @@ -185,10 +181,17 @@ export class QuickBar extends LitElement { private _handleInputKeyDown(ev: KeyboardEvent) { if (ev.code === "Enter") { - this._firstListItem?.click(); + // wait for debounce + setTimeout(() => { + if (!this._items?.length) { + return; + } + + this.processItemAndCloseDialog(this._items[0], 0); + }, 100); } else if (ev.code === "ArrowDown") { ev.preventDefault(); - this._firstListItem?.focus(); + this._list?.focus(); } } From 3f53143dfb2caa7ba0538ff6ea158ae9ed3c8c2e Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Fri, 16 Oct 2020 22:29:56 +0200 Subject: [PATCH 03/11] remove debounce --- src/common/string/filter/sequence-matching.ts | 1 + src/dialogs/quick-bar/ha-quick-bar.ts | 24 ++++++++++++------- src/resources/styles.ts | 1 + 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/common/string/filter/sequence-matching.ts b/src/common/string/filter/sequence-matching.ts index e870ffe976ae..f8ea1f40cf88 100644 --- a/src/common/string/filter/sequence-matching.ts +++ b/src/common/string/filter/sequence-matching.ts @@ -59,6 +59,7 @@ export const fuzzyFilterSort: FuzzyFilterSort = (filter, items) => { : fuzzySequentialMatch(filter, item.text); return item; }) + .filter((item) => item.score === undefined || item.score > 0) .sort(({ score: scoreA = 0 }, { score: scoreB = 0 }) => scoreA > scoreB ? -1 : scoreA < scoreB ? 1 : 0 ); diff --git a/src/dialogs/quick-bar/ha-quick-bar.ts b/src/dialogs/quick-bar/ha-quick-bar.ts index 2e06ca4720b2..fa25f14d023d 100644 --- a/src/dialogs/quick-bar/ha-quick-bar.ts +++ b/src/dialogs/quick-bar/ha-quick-bar.ts @@ -181,14 +181,11 @@ export class QuickBar extends LitElement { private _handleInputKeyDown(ev: KeyboardEvent) { if (ev.code === "Enter") { - // wait for debounce - setTimeout(() => { - if (!this._items?.length) { - return; - } + if (!this._items?.length) { + return; + } - this.processItemAndCloseDialog(this._items[0], 0); - }, 100); + this.processItemAndCloseDialog(this._items[0], 0); } else if (ev.code === "ArrowDown") { ev.preventDefault(); this._list?.focus(); @@ -272,8 +269,13 @@ export class QuickBar extends LitElement { } private _filterItems = memoizeOne( - (items: QuickBarItem[], filter: string): QuickBarItem[] => - fuzzyFilterSort(filter.trimLeft(), items) + (items: QuickBarItem[], filter: string): QuickBarItem[] => { + const filteredAndSortedItems = fuzzyFilterSort( + filter.trimLeft(), + items + ); + return filteredAndSortedItems; + } ); static get styles() { @@ -304,6 +306,10 @@ export class QuickBar extends LitElement { } } + ha-icon { + color: var(--secondary-text-color); + } + ha-svg-icon.prefix { margin: 8px; } diff --git a/src/resources/styles.ts b/src/resources/styles.ts index 9525b89f86c6..695a27d67047 100644 --- a/src/resources/styles.ts +++ b/src/resources/styles.ts @@ -74,6 +74,7 @@ export const derivedStyles = { "mdc-theme-on-secondary": "var(--text-primary-color)", "mdc-theme-on-surface": "var(--primary-text-color)", "mdc-theme-text-primary-on-background": "var(--primary-text-color)", + "mdc-theme-text-secondary-on-background": "var(--secondary-text-color)", "app-header-text-color": "var(--text-primary-color)", "app-header-background-color": "var(--primary-color)", "material-body-text-color": "var(--primary-text-color)", From aee421099f870241ffeddf32bea7901b3c49c814 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Tue, 20 Oct 2020 22:48:03 +0200 Subject: [PATCH 04/11] Fix selected --- src/dialogs/quick-bar/ha-quick-bar.ts | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/dialogs/quick-bar/ha-quick-bar.ts b/src/dialogs/quick-bar/ha-quick-bar.ts index fa25f14d023d..70c0b97e724e 100644 --- a/src/dialogs/quick-bar/ha-quick-bar.ts +++ b/src/dialogs/quick-bar/ha-quick-bar.ts @@ -32,6 +32,7 @@ import "../../common/search/search-input"; import { mdiConsoleLine } from "@mdi/js"; import { scroll } from "lit-virtualizer"; import { styleMap } from "lit-html/directives/style-map"; +import { SingleSelectedEvent } from "@material/mwc-list/mwc-list-foundation"; interface QuickBarItem extends ScorableTextItem { icon: string; @@ -124,7 +125,7 @@ export class QuickBar extends LitElement { >` : html` Date: Tue, 20 Oct 2020 23:42:27 +0200 Subject: [PATCH 05/11] Set items after animation finished --- src/dialogs/quick-bar/ha-quick-bar.ts | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/dialogs/quick-bar/ha-quick-bar.ts b/src/dialogs/quick-bar/ha-quick-bar.ts index 70c0b97e724e..8f6203640136 100644 --- a/src/dialogs/quick-bar/ha-quick-bar.ts +++ b/src/dialogs/quick-bar/ha-quick-bar.ts @@ -82,8 +82,7 @@ export class QuickBar extends LitElement { protected updated(changedProperties: PropertyValues) { if ( this._opened && - (changedProperties.has("_opened") || - changedProperties.has("_filter") || + (changedProperties.has("_filter") || changedProperties.has("_commandMode")) ) { this._setFilteredItems(); @@ -96,7 +95,13 @@ export class QuickBar extends LitElement { } return html` - + Date: Wed, 21 Oct 2020 00:17:18 +0200 Subject: [PATCH 06/11] Fix styling of virtualized list --- src/dialogs/quick-bar/ha-quick-bar.ts | 28 +++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/src/dialogs/quick-bar/ha-quick-bar.ts b/src/dialogs/quick-bar/ha-quick-bar.ts index 8f6203640136..64ed9f9957bb 100644 --- a/src/dialogs/quick-bar/ha-quick-bar.ts +++ b/src/dialogs/quick-bar/ha-quick-bar.ts @@ -59,6 +59,8 @@ export class QuickBar extends LitElement { @internalProperty() private _activatedIndex = 0; + @internalProperty() private _done = false; + @query("search-input", false) private _filterInputField?: HTMLElement; @query("mwc-list", false) private _list?: HTMLElement; @@ -72,6 +74,7 @@ export class QuickBar extends LitElement { public closeDialog() { this._opened = false; + this._done = false; this._filter = ""; this._commandTriggered = -1; this._items = []; @@ -132,13 +135,16 @@ export class QuickBar extends LitElement { activatable @selected=${this._handleSelected} style=${styleMap({ - height: `${Math.min(this._items.length * 72 + 26, 500)}px`, + height: `${Math.min( + this._items.length * (this._commandMode ? 56 : 72) + 26, + this._done ? 500 : 0 + )}px`, })} > ${scroll({ - items: this._items as [], + items: this._items, renderItem: (item: QuickBarItem, index?: number) => - this.renderItem(item, index), + this._renderItem(item, index), })} `} @@ -147,9 +153,12 @@ export class QuickBar extends LitElement { private _handleOpened() { this._setFilteredItems(); + this.updateComplete.then(() => { + this._done = true; + }); } - private renderItem(item: QuickBarItem, index?: number) { + private _renderItem(item: QuickBarItem, index?: number) { return html` compare(a.text.toLowerCase(), b.text.toLowerCase())); } - private async _setFilteredItems() { + private _setFilteredItems() { const items = this._commandMode ? this._commandItems : this._entityItems; this._items = this._filter ? this._filterItems(items || [], this._filter) @@ -285,13 +294,8 @@ export class QuickBar extends LitElement { } private _filterItems = memoizeOne( - (items: QuickBarItem[], filter: string): QuickBarItem[] => { - const filteredAndSortedItems = fuzzyFilterSort( - filter.trimLeft(), - items - ); - return filteredAndSortedItems; - } + (items: QuickBarItem[], filter: string): QuickBarItem[] => + fuzzyFilterSort(filter.trimLeft(), items) ); static get styles() { From 21522b625d9dc5bfb6f64fac106db378ee7cc46d Mon Sep 17 00:00:00 2001 From: Donnie Date: Tue, 20 Oct 2020 16:12:37 -0700 Subject: [PATCH 07/11] Fix issue with first list item not being selected --- src/dialogs/quick-bar/ha-quick-bar.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dialogs/quick-bar/ha-quick-bar.ts b/src/dialogs/quick-bar/ha-quick-bar.ts index 8f6203640136..a1f242924f2d 100644 --- a/src/dialogs/quick-bar/ha-quick-bar.ts +++ b/src/dialogs/quick-bar/ha-quick-bar.ts @@ -61,7 +61,7 @@ export class QuickBar extends LitElement { @query("search-input", false) private _filterInputField?: HTMLElement; - @query("mwc-list", false) private _list?: HTMLElement; + @query("mwc-list-item", false) private _firstListItem?: HTMLElement; public async showDialog(params: QuickBarParams) { this._commandMode = params.commandMode || false; @@ -204,7 +204,7 @@ export class QuickBar extends LitElement { this.processItemAndCloseDialog(this._items[0], 0); } else if (ev.code === "ArrowDown") { ev.preventDefault(); - this._list?.focus(); + this._firstListItem?.focus(); } } From e8f8a14668a161c1dfe27c6e13a05c59f7c49ea0 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Wed, 21 Oct 2020 12:02:06 +0200 Subject: [PATCH 08/11] Tweaks --- src/dialogs/quick-bar/ha-quick-bar.ts | 54 ++++++++++++++++----------- 1 file changed, 33 insertions(+), 21 deletions(-) diff --git a/src/dialogs/quick-bar/ha-quick-bar.ts b/src/dialogs/quick-bar/ha-quick-bar.ts index dcf153a18bfb..a2c4d6053dc9 100644 --- a/src/dialogs/quick-bar/ha-quick-bar.ts +++ b/src/dialogs/quick-bar/ha-quick-bar.ts @@ -33,6 +33,9 @@ import { mdiConsoleLine } from "@mdi/js"; import { scroll } from "lit-virtualizer"; import { styleMap } from "lit-html/directives/style-map"; import { SingleSelectedEvent } from "@material/mwc-list/mwc-list-foundation"; +import type { List } from "@material/mwc-list/mwc-list"; +import type { ListItem } from "@material/mwc-list/mwc-list-item"; +import { ifDefined } from "lit-html/directives/if-defined"; interface QuickBarItem extends ScorableTextItem { icon: string; @@ -57,18 +60,17 @@ export class QuickBar extends LitElement { @internalProperty() private _commandTriggered = -1; - @internalProperty() private _activatedIndex = 0; - @internalProperty() private _done = false; @query("search-input", false) private _filterInputField?: HTMLElement; - @query("mwc-list-item", false) private _firstListItem?: HTMLElement; + private _focusSet = false; public async showDialog(params: QuickBarParams) { this._commandMode = params.commandMode || false; this._commandItems = this._generateCommandItems(); this._entityItems = this._generateEntityItems(); + this._focusSet = false; this._opened = true; } @@ -78,7 +80,6 @@ export class QuickBar extends LitElement { this._filter = ""; this._commandTriggered = -1; this._items = []; - this._resetActivatedIndex(); fireEvent(this, "dialog-closed", { dialog: this.localName }); } @@ -116,7 +117,7 @@ export class QuickBar extends LitElement { )} .filter=${this._commandMode ? `>${this._filter}` : this._filter} @keydown=${this._handleInputKeyDown} - @focus=${this._resetActivatedIndex} + @focus=${this._setFocusFirstListItem} > ${this._commandMode ? html`` : html` -1) { + this._setFocusFirstListItem(); + } + } + private _renderItem(item: QuickBarItem, index?: number) { return html` @@ -194,13 +204,9 @@ export class QuickBar extends LitElement { this.closeDialog(); } - private _resetActivatedIndex() { - this._activatedIndex = 0; - } - private _handleSelected(ev: SingleSelectedEvent) { const index = ev.detail.index; - const item = (ev.target as any).items[index].item; + const item = ((ev.target as List).items[index] as any).item; this.processItemAndCloseDialog(item, index); } @@ -213,10 +219,15 @@ export class QuickBar extends LitElement { this.processItemAndCloseDialog(this._items[0], 0); } else if (ev.code === "ArrowDown") { ev.preventDefault(); - this._firstListItem?.focus(); + this._getItemAtIndex(0)?.focus(); + this._getItemAtIndex(1)?.focus(); } } + private _getItemAtIndex(index: number): ListItem | null { + return this.renderRoot.querySelector(`mwc-list-item[index="${index}"]`); + } + private _handleSearchChange(ev: CustomEvent): void { const newFilter = ev.detail.value; const oldCommandMode = this._commandMode; @@ -234,22 +245,23 @@ export class QuickBar extends LitElement { } } + private _setFocusFirstListItem() { + // @ts-ignore + this._getItemAtIndex(0)?.rippleHandlers.startFocus(); + } + private _handleListItemKeyDown(ev: KeyboardEvent) { const isSingleCharacter = ev.key.length === 1; - const isFirstListItem = (ev.target as any).index === 0; + const isFirstListItem = + (ev.target as HTMLElement).getAttribute("index") === "0"; if (ev.key === "ArrowUp") { if (isFirstListItem) { this._filterInputField?.focus(); - } else { - this._activatedIndex--; } - } else if (ev.key === "ArrowDown") { - this._activatedIndex++; } - if (ev.key === "Backspace" || isSingleCharacter) { + (ev.currentTarget as List).scrollTop = 0; this._filterInputField?.focus(); - this._resetActivatedIndex(); } } From 31441f2a8cfcafab82d40c965c1164213efdf574 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Wed, 21 Oct 2020 12:18:55 +0200 Subject: [PATCH 09/11] Add debounce back --- src/dialogs/quick-bar/ha-quick-bar.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/dialogs/quick-bar/ha-quick-bar.ts b/src/dialogs/quick-bar/ha-quick-bar.ts index a2c4d6053dc9..a78308b5575f 100644 --- a/src/dialogs/quick-bar/ha-quick-bar.ts +++ b/src/dialogs/quick-bar/ha-quick-bar.ts @@ -36,6 +36,7 @@ import { SingleSelectedEvent } from "@material/mwc-list/mwc-list-foundation"; import type { List } from "@material/mwc-list/mwc-list"; import type { ListItem } from "@material/mwc-list/mwc-list-item"; import { ifDefined } from "lit-html/directives/if-defined"; +import { debounce } from "../../common/util/debounce"; interface QuickBarItem extends ScorableTextItem { icon: string; @@ -234,10 +235,10 @@ export class QuickBar extends LitElement { if (newFilter.startsWith(">")) { this._commandMode = true; - this._filter = newFilter.substring(1); + this._debouncedSetFilter(newFilter.substring(1)); } else { this._commandMode = false; - this._filter = newFilter; + this._debouncedSetFilter(newFilter); } if (oldCommandMode !== this._commandMode) { @@ -245,6 +246,10 @@ export class QuickBar extends LitElement { } } + private _debouncedSetFilter = debounce((filter: string) => { + this._filter = filter; + }, 100); + private _setFocusFirstListItem() { // @ts-ignore this._getItemAtIndex(0)?.rippleHandlers.startFocus(); From 7e0ce6fdf6037bf6ac88e737ebbc62dc05dc5926 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Wed, 21 Oct 2020 12:19:27 +0200 Subject: [PATCH 10/11] Organize imports (for Zack) --- src/dialogs/quick-bar/ha-quick-bar.ts | 42 +++++++++++++-------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/src/dialogs/quick-bar/ha-quick-bar.ts b/src/dialogs/quick-bar/ha-quick-bar.ts index a78308b5575f..f712f466f3b9 100644 --- a/src/dialogs/quick-bar/ha-quick-bar.ts +++ b/src/dialogs/quick-bar/ha-quick-bar.ts @@ -1,7 +1,9 @@ -import "../../components/ha-circular-progress"; -import "../../components/ha-header-bar"; -import "@material/mwc-list/mwc-list-item"; import "@material/mwc-list/mwc-list"; +import type { List } from "@material/mwc-list/mwc-list"; +import { SingleSelectedEvent } from "@material/mwc-list/mwc-list-foundation"; +import "@material/mwc-list/mwc-list-item"; +import type { ListItem } from "@material/mwc-list/mwc-list-item"; +import { mdiConsoleLine } from "@mdi/js"; import { css, customElement, @@ -12,31 +14,29 @@ import { PropertyValues, query, } from "lit-element"; +import { ifDefined } from "lit-html/directives/if-defined"; +import { styleMap } from "lit-html/directives/style-map"; +import { scroll } from "lit-virtualizer"; +import memoizeOne from "memoize-one"; +import { componentsWithService } from "../../common/config/components_with_service"; import { fireEvent } from "../../common/dom/fire_event"; -import "../../components/ha-dialog"; -import { haStyleDialog } from "../../resources/styles"; +import { computeDomain } from "../../common/entity/compute_domain"; +import { computeStateName } from "../../common/entity/compute_state_name"; +import { domainIcon } from "../../common/entity/domain_icon"; +import "../../common/search/search-input"; +import { compare } from "../../common/string/compare"; import { fuzzyFilterSort, ScorableTextItem, } from "../../common/string/filter/sequence-matching"; -import { HomeAssistant } from "../../types"; -import { componentsWithService } from "../../common/config/components_with_service"; -import { domainIcon } from "../../common/entity/domain_icon"; -import { computeDomain } from "../../common/entity/compute_domain"; +import { debounce } from "../../common/util/debounce"; +import "../../components/ha-circular-progress"; +import "../../components/ha-dialog"; +import "../../components/ha-header-bar"; import { domainToName } from "../../data/integration"; +import { haStyleDialog } from "../../resources/styles"; +import { HomeAssistant } from "../../types"; import { QuickBarParams } from "./show-dialog-quick-bar"; -import { compare } from "../../common/string/compare"; -import { computeStateName } from "../../common/entity/compute_state_name"; -import memoizeOne from "memoize-one"; -import "../../common/search/search-input"; -import { mdiConsoleLine } from "@mdi/js"; -import { scroll } from "lit-virtualizer"; -import { styleMap } from "lit-html/directives/style-map"; -import { SingleSelectedEvent } from "@material/mwc-list/mwc-list-foundation"; -import type { List } from "@material/mwc-list/mwc-list"; -import type { ListItem } from "@material/mwc-list/mwc-list-item"; -import { ifDefined } from "lit-html/directives/if-defined"; -import { debounce } from "../../common/util/debounce"; interface QuickBarItem extends ScorableTextItem { icon: string; From 4f09512285a4f4470ef0bd3b3b51aa1201a23041 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Wed, 21 Oct 2020 12:31:05 +0200 Subject: [PATCH 11/11] Update ha-quick-bar.ts --- src/dialogs/quick-bar/ha-quick-bar.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/dialogs/quick-bar/ha-quick-bar.ts b/src/dialogs/quick-bar/ha-quick-bar.ts index f712f466f3b9..2f204be37239 100644 --- a/src/dialogs/quick-bar/ha-quick-bar.ts +++ b/src/dialogs/quick-bar/ha-quick-bar.ts @@ -71,13 +71,13 @@ export class QuickBar extends LitElement { this._commandMode = params.commandMode || false; this._commandItems = this._generateCommandItems(); this._entityItems = this._generateEntityItems(); - this._focusSet = false; this._opened = true; } public closeDialog() { this._opened = false; this._done = false; + this._focusSet = false; this._filter = ""; this._commandTriggered = -1; this._items = []; @@ -162,11 +162,13 @@ export class QuickBar extends LitElement { }); } - private _handleRangeChanged(e) { + private async _handleRangeChanged(e) { if (this._focusSet) { return; } if (e.firstVisible > -1) { + this._focusSet = true; + await this.updateComplete; this._setFocusFirstListItem(); } }