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 type { Chunks, Icons } from "../data/iconsets";
import { import {
MDI_PREFIXES, MDI_PREFIXES,
checkCacheVersion,
findIconChunk, findIconChunk,
getIcon, getIcon,
writeCache, writeCache,
@ -26,11 +25,6 @@ const mdiDeprecatedIcons: DeprecatedIcon = {};
const chunks: Chunks = {}; 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 debouncedWriteCache = debounce(() => writeCache(chunks), 2000);
const cachedIcons: Record<string, string> = {}; const cachedIcons: Record<string, string> = {};

View File

@ -1,4 +1,5 @@
import { clear, get, set, createStore, promisifyRequest } from "idb-keyval"; import { clear, get, set, createStore, promisifyRequest } from "idb-keyval";
import memoizeOne from "memoize-one";
import { promiseTimeout } from "../common/util/promise-timeout"; import { promiseTimeout } from "../common/util/promise-timeout";
import { iconMetadata } from "../resources/icon-metadata"; import { iconMetadata } from "../resources/icon-metadata";
import type { IconMeta } from "../types"; import type { IconMeta } from "../types";
@ -11,7 +12,23 @@ export interface Chunks {
[key: string]: Promise<Icons>; [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"]; export const MDI_PREFIXES = ["mdi", "hass", "hassio", "hademo"];
@ -28,7 +45,10 @@ export const getIcon = (iconName: string) =>
return; 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) => { iconStore("readonly", (store) => {
for (const [iconName_, resolve_, reject_] of toRead) { for (const [iconName_, resolve_, reject_] of toRead) {
promisifyRequest<string | undefined>(store.get(iconName_)) promisifyRequest<string | undefined>(store.get(iconName_))
@ -37,6 +57,7 @@ export const getIcon = (iconName: string) =>
} }
toRead = []; toRead = [];
}); });
};
promiseTimeout(1000, readIcons()).catch((e) => { promiseTimeout(1000, readIcons()).catch((e) => {
// Firefox in private mode doesn't support IDB // Firefox in private mode doesn't support IDB
@ -62,6 +83,7 @@ export const findIconChunk = (icon: string): string => {
export const writeCache = async (chunks: Chunks) => { export const writeCache = async (chunks: Chunks) => {
const keys = Object.keys(chunks); const keys = Object.keys(chunks);
const iconsSets: Icons[] = await Promise.all(Object.values(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 // We do a batch opening the store just once, for (considerable) performance
iconStore("readwrite", (store) => { iconStore("readwrite", (store) => {
iconsSets.forEach((icons, idx) => { 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);
}
};