From 20d3681da304fd286cfd6b2861a0695724e03b59 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Mon, 4 Nov 2024 05:26:45 -0500 Subject: [PATCH] Delay loading IndexedDB to when first icon is requested (#22637) --- src/components/ha-icon.ts | 6 ------ src/data/iconsets.ts | 37 ++++++++++++++++++++++++------------- 2 files changed, 24 insertions(+), 19 deletions(-) diff --git a/src/components/ha-icon.ts b/src/components/ha-icon.ts index 41bbe25433..3428deaada 100644 --- a/src/components/ha-icon.ts +++ b/src/components/ha-icon.ts @@ -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 = {}; diff --git a/src/data/iconsets.ts b/src/data/iconsets.ts index 9cee9041c5..5bf8f1671e 100644 --- a/src/data/iconsets.ts +++ b/src/data/iconsets.ts @@ -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; } -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(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); - } -};