Skip to content

Commit

Permalink
do icon search in a background thread
Browse files Browse the repository at this point in the history
  • Loading branch information
piitaya committed Nov 17, 2022
1 parent 9e35f43 commit ba9f311
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 26 deletions.
36 changes: 10 additions & 26 deletions src/components/ha-icon-picker.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { css, html, LitElement, PropertyValues, TemplateResult } from "lit";
import { ComboBoxLitRenderer } from "@vaadin/combo-box/lit";
import { css, html, LitElement, PropertyValues, TemplateResult } from "lit";
import { customElement, property, state } from "lit/decorators";
import { fireEvent } from "../common/dom/fire_event";
import { customIcons } from "../data/custom_icons";
import { PolymerChangedEvent } from "../polymer-types";
import { filterIconItems } from "../resources/filter-icon-items";
import { HomeAssistant } from "../types";
import "./ha-combo-box";
import "./ha-icon";
Expand Down Expand Up @@ -150,35 +151,18 @@ export class HaIconPicker extends LitElement {
);
}

private _filterChanged(ev: CustomEvent): void {
private async _filterChanged(ev: CustomEvent): Promise<void> {
const filterString = ev.detail.value.toLowerCase();
const characterCount = filterString.length;
if (characterCount >= 2) {
const filteredItems: IconItem[] = [];
const filteredItemsByKeywords: IconItem[] = [];

iconItems.forEach((item) => {
if (item.icon.includes(filterString)) {
filteredItems.push(item);
return;
}
if (item.keywords.some((t) => t.includes(filterString))) {
filteredItemsByKeywords.push(item);
}
});

filteredItems.push(...filteredItemsByKeywords);
const filteredItems: IconItem[] = await filterIconItems(
filterString,
iconItems
);

if (filteredItems.length > 0) {
// Setting it sync cause browser freeze when user paste an icon text
setTimeout(() => {
this._filteredItems = filteredItems;
}, 1);
} else {
this._filteredItems = [{ icon: filterString, keywords: [] }];
}
if (filteredItems.length > 0) {
this._filteredItems = filteredItems;
} else {
this._filteredItems = iconItems;
this._filteredItems = [{ icon: filterString, keywords: [] }];
}
}

Expand Down
17 changes: 17 additions & 0 deletions src/resources/filter-icon-items.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { Remote, wrap } from "comlink";
import type { Api } from "./icon-worker";

type FilterIconItemsType = Api["filterIconItems"];
type FilterIconItemsParamTypes = Parameters<FilterIconItemsType>;

let worker: Remote<Api> | undefined;

export const filterIconItems = async (
...arg: FilterIconItemsParamTypes
): Promise<ReturnType<FilterIconItemsType>> => {
if (!worker) {
worker = wrap(new Worker(new URL("./icon-worker", import.meta.url)));
}

return worker.filterIconItems(...arg);
};
42 changes: 42 additions & 0 deletions src/resources/icon-worker.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// To use comlink under ES5
import { expose } from "comlink";
import "proxy-polyfill";

type IconItem = {
icon: string;
keywords: string[];
};

const filterIconItems = (
filterString: string,
iconItems: IconItem[]
): IconItem[] => {
if (filterString.length === 0) {
return iconItems;
}

const filteredItems: IconItem[] = [];
const filteredItemsByKeywords: IconItem[] = [];

iconItems.forEach((item) => {
if (item.icon.includes(filterString)) {
filteredItems.push(item);
return;
}
if (item.keywords.some((t) => t.includes(filterString))) {
filteredItemsByKeywords.push(item);
}
});

filteredItems.push(...filteredItemsByKeywords);

return filteredItems;
};

const api = {
filterIconItems,
};

export type Api = typeof api;

expose(api);

0 comments on commit ba9f311

Please sign in to comment.