Delay loading IndexedDB to when first icon is requested (#22637)

This commit is contained in:
Paulus Schoutsen 2024-11-04 05:26:45 -05:00 committed by GitHub
parent 9b97274bf6
commit 20d3681da3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 24 additions and 19 deletions

View File

@ -8,7 +8,6 @@ import { customIcons } from "../data/custom_icons";
import type { Chunks, Icons } from "../data/iconsets";
import {
MDI_PREFIXES,
checkCacheVersion,
findIconChunk,
getIcon,
writeCache,
@ -26,11 +25,6 @@ const mdiDeprecatedIcons: DeprecatedIcon = {};
const chunks: Chunks = {};
// Supervisor doesn't use icons, and should not update/downgrade the icon DB.
if (!__SUPERVISOR__) {
checkCacheVersion();
}
const debouncedWriteCache = debounce(() => writeCache(chunks), 2000);
const cachedIcons: Record<string, string> = {};

View File

@ -1,4 +1,5 @@
import { clear, get, set, createStore, promisifyRequest } from "idb-keyval";
import memoizeOne from "memoize-one";
import { promiseTimeout } from "../common/util/promise-timeout";
import { iconMetadata } from "../resources/icon-metadata";
import type { IconMeta } from "../types";
@ -11,7 +12,23 @@ export interface Chunks {
[key: string]: Promise<Icons>;
}
export const iconStore = createStore("hass-icon-db", "mdi-icon-store");
const getStore = memoizeOne(async () => {
const iconStore = createStore("hass-icon-db", "mdi-icon-store");
// Supervisor doesn't use icons, and should not update/downgrade the icon DB.
if (!__SUPERVISOR__) {
const version = await get("_version", iconStore);
if (!version) {
set("_version", iconMetadata.version, iconStore);
} else if (version !== iconMetadata.version) {
await clear(iconStore);
set("_version", iconMetadata.version, iconStore);
}
}
return iconStore;
});
export const MDI_PREFIXES = ["mdi", "hass", "hassio", "hademo"];
@ -28,7 +45,10 @@ export const getIcon = (iconName: string) =>
return;
}
const readIcons = () =>
// Start initializing the store, so it's ready when we need it
const iconStoreProm = getStore();
const readIcons = async () => {
const iconStore = await iconStoreProm;
iconStore("readonly", (store) => {
for (const [iconName_, resolve_, reject_] of toRead) {
promisifyRequest<string | undefined>(store.get(iconName_))
@ -37,6 +57,7 @@ export const getIcon = (iconName: string) =>
}
toRead = [];
});
};
promiseTimeout(1000, readIcons()).catch((e) => {
// Firefox in private mode doesn't support IDB
@ -62,6 +83,7 @@ export const findIconChunk = (icon: string): string => {
export const writeCache = async (chunks: Chunks) => {
const keys = Object.keys(chunks);
const iconsSets: Icons[] = await Promise.all(Object.values(chunks));
const iconStore = await getStore();
// We do a batch opening the store just once, for (considerable) performance
iconStore("readwrite", (store) => {
iconsSets.forEach((icons, idx) => {
@ -72,14 +94,3 @@ export const writeCache = async (chunks: Chunks) => {
});
});
};
export const checkCacheVersion = async () => {
const version = await get("_version", iconStore);
if (!version) {
set("_version", iconMetadata.version, iconStore);
} else if (version !== iconMetadata.version) {
await clear(iconStore);
set("_version", iconMetadata.version, iconStore);
}
};