From 01f51f3247feeeaace76088500fb2066fa5fd049 Mon Sep 17 00:00:00 2001 From: Steve Repsher Date: Wed, 25 Oct 2023 03:28:28 -0400 Subject: [PATCH] Cache brand images (#17840) --- src/components/entity/state-badge.ts | 17 ++--- src/components/ha-config-entry-picker.ts | 1 + src/components/ha-related-items.ts | 2 + src/entrypoints/service_worker.ts | 65 ++++++++++++------- src/onboarding/integration-badge.ts | 1 + .../config/dashboard/ha-config-updates.ts | 13 ++-- .../config/devices/ha-config-device-page.ts | 2 + .../devices/ha-config-devices-dashboard.ts | 1 + .../components/ha-energy-grid-settings.ts | 2 + .../dialogs/dialog-energy-solar-settings.ts | 1 + .../config/hardware/ha-config-hardware.ts | 9 ++- .../config/helpers/dialog-helper-detail.ts | 3 +- .../ha-config-integration-page.ts | 1 + .../integrations/ha-domain-integrations.ts | 3 + .../ha-integration-action-card.ts | 1 + .../integrations/ha-integration-header.ts | 1 + .../integrations/ha-integration-list-item.ts | 1 + .../thread/thread-config-panel.ts | 1 + .../config/repairs/ha-config-repairs.ts | 1 + .../repairs/integrations-startup-time.ts | 1 + .../config/voice-assistants/assist-pref.ts | 1 + .../voice-assistants/cloud-alexa-pref.ts | 1 + .../config/voice-assistants/cloud-discover.ts | 2 + .../voice-assistants/cloud-google-pref.ts | 1 + .../voice-assistants/entity-voice-settings.ts | 1 + .../expose/expose-assistant-icon.ts | 1 + 26 files changed, 94 insertions(+), 40 deletions(-) diff --git a/src/components/entity/state-badge.ts b/src/components/entity/state-badge.ts index 7e19d97e4867..4ef0166fc970 100644 --- a/src/components/entity/state-badge.ts +++ b/src/components/entity/state-badge.ts @@ -112,9 +112,7 @@ export class StateBadge extends LitElement { const stateObj = this.stateObj; const iconStyle: { [name: string]: string } = {}; - const hostStyle: Partial = { - backgroundImage: "", - }; + let backgroundImage = ""; this._showIcon = true; @@ -135,13 +133,12 @@ export class StateBadge extends LitElement { if (domain === "camera") { imageUrl = cameraUrlWithWidthHeight(imageUrl, 80, 80); } - hostStyle.backgroundImage = `url(${imageUrl})`; + backgroundImage = `url(${imageUrl})`; this._showIcon = false; if (domain === "update") { - hostStyle.borderRadius = "0"; - } - if (domain === "media_player") { - hostStyle.borderRadius = "8%"; + this.style.borderRadius = "0"; + } else if (domain === "media_player") { + this.style.borderRadius = "8%"; } } else if (this.color) { // Externally provided overriding color wins over state color @@ -182,12 +179,12 @@ export class StateBadge extends LitElement { if (this.hass) { imageUrl = this.hass.hassUrl(imageUrl); } - hostStyle.backgroundImage = `url(${imageUrl})`; + backgroundImage = `url(${imageUrl})`; this._showIcon = false; } this._iconStyle = iconStyle; - Object.assign(this.style, hostStyle); + this.style.backgroundImage = backgroundImage; } static get styles(): CSSResultGroup { diff --git a/src/components/ha-config-entry-picker.ts b/src/components/ha-config-entry-picker.ts index 65f2064931a6..4d8e9f885952 100644 --- a/src/components/ha-config-entry-picker.ts +++ b/src/components/ha-config-entry-picker.ts @@ -64,6 +64,7 @@ class HaConfigEntryPicker extends LitElement { type: "icon", darkOptimized: this.hass.themes?.darkMode, })} + crossorigin="anonymous" referrerpolicy="no-referrer" @error=${this._onImageError} @load=${this._onImageLoad} diff --git a/src/components/ha-related-items.ts b/src/components/ha-related-items.ts index 0bed712acd92..b843cd2ba9f1 100644 --- a/src/components/ha-related-items.ts +++ b/src/components/ha-related-items.ts @@ -154,6 +154,8 @@ export class HaRelatedItems extends LitElement { useFallback: true, darkOptimized: this.hass.themes?.darkMode, })} + crossorigin="anonymous" + referrerpolicy="no-referrer" alt=${entry.domain} slot="graphic" /> diff --git a/src/entrypoints/service_worker.ts b/src/entrypoints/service_worker.ts index da8fbd847163..4b7e262f3bd6 100644 --- a/src/entrypoints/service_worker.ts +++ b/src/entrypoints/service_worker.ts @@ -2,8 +2,8 @@ // eslint-disable-next-line spaced-comment /// /* eslint-env serviceworker */ -import { CacheableResponsePlugin } from "workbox-cacheable-response"; import { cacheNames, RouteHandler } from "workbox-core"; +import { CacheableResponsePlugin } from "workbox-cacheable-response"; import { ExpirationPlugin } from "workbox-expiration"; import { cleanupOutdatedCaches, precacheAndRoute } from "workbox-precaching"; import { registerRoute, setCatchHandler } from "workbox-routing"; @@ -15,11 +15,8 @@ import { const noFallBackRegEx = /\/(api|static|auth|frontend_latest|frontend_es5|local)\/.*/; -// Clean up caches from older workboxes and old service workers. -// Will help with cleaning up Workbox v4 stuff -cleanupOutdatedCaches(); -function initRouting() { +const initRouting = () => { precacheAndRoute( // @ts-ignore WB_MANIFEST, @@ -35,6 +32,27 @@ function initRouting() { new CacheFirst({ matchOptions: { ignoreSearch: true } }) ); + // Cache any brand images used for 30 days + // Use revalidation so cache is always available during an extended outage + registerRoute( + ({ url, request }) => + url.origin === "https://brands.home-assistant.io" && + request.destination === "image", + new StaleWhileRevalidate({ + cacheName: "brands", + // CORS must be forced to work for CSS images + fetchOptions: { mode: "cors", credentials: "omit" }, + plugins: [ + // Add 404 so we quicly respond to domains with missing images + new CacheableResponsePlugin({ statuses: [0, 200, 404] }), + new ExpirationPlugin({ + maxAgeSeconds: 60 * 60 * 24 * 30, + purgeOnQuotaError: true, + }), + ], + }) + ); + // Get api from network. registerRoute(/\/(api|auth)\/.*/, new NetworkOnly()); @@ -59,18 +77,16 @@ function initRouting() { new StaleWhileRevalidate({ cacheName: "file-cache", plugins: [ - new CacheableResponsePlugin({ - statuses: [0, 200], - }), new ExpirationPlugin({ maxAgeSeconds: 60 * 60 * 24, + purgeOnQuotaError: true, }), ], }) ); -} +}; -function initPushNotifications() { +const initPushNotifications = () => { // HTML5 Push Notifications function firePushCallback(payload, jwt) { // Don't send the JWT in the payload.data @@ -176,7 +192,20 @@ function initPushNotifications() { self.addEventListener("notificationclose", (event) => { notificationEventCallback("closed", event); }); -} +}; + +const catchHandler: RouteHandler = async (options) => { + const dest = (options.request as Request).destination; + const url = (options.request as Request).url; + + if (dest !== "document" || noFallBackRegEx.test(url)) { + return Response.error(); + } + // eslint-disable-next-line no-console + console.log("Using fallback for:", url); + + return (await caches.match("/", { ignoreSearch: true })) || Response.error(); +}; self.addEventListener("install", (event) => { // Delete all runtime caching, so that index.html has to be refetched. @@ -206,19 +235,7 @@ self.addEventListener("message", (message) => { } }); -const catchHandler: RouteHandler = async (options) => { - const dest = (options.request as Request).destination; - const url = (options.request as Request).url; - - if (dest !== "document" || noFallBackRegEx.test(url)) { - return Response.error(); - } - // eslint-disable-next-line no-console - console.log("Using fallback for:", url); - - return (await caches.match("/", { ignoreSearch: true })) || Response.error(); -}; - +cleanupOutdatedCaches(); initRouting(); setCatchHandler(catchHandler); initPushNotifications(); diff --git a/src/onboarding/integration-badge.ts b/src/onboarding/integration-badge.ts index e888460046b2..be4b7ec8ef6f 100644 --- a/src/onboarding/integration-badge.ts +++ b/src/onboarding/integration-badge.ts @@ -23,6 +23,7 @@ class IntegrationBadge extends LitElement { type: "icon", darkOptimized: this.darkOptimizedIcon, })} + crossorigin="anonymous" referrerpolicy="no-referrer" /> diff --git a/src/panels/config/dashboard/ha-config-updates.ts b/src/panels/config/dashboard/ha-config-updates.ts index ece376c8e810..718ca7bf8144 100644 --- a/src/panels/config/dashboard/ha-config-updates.ts +++ b/src/panels/config/dashboard/ha-config-updates.ts @@ -3,6 +3,7 @@ import "@material/mwc-list/mwc-list"; import { UnsubscribeFunc } from "home-assistant-js-websocket"; import { css, CSSResultGroup, html, LitElement, nothing } from "lit"; import { customElement, property } from "lit/decorators"; +import { ifDefined } from "lit/directives/if-defined"; import memoizeOne from "memoize-one"; import { fireEvent } from "../../../common/dom/fire_event"; import "../../../components/entity/state-badge"; @@ -87,7 +88,9 @@ class HaConfigUpdates extends SubscribeMixin(LitElement) { ${this.narrow && entity.attributes.in_progress ? html` @@ -741,6 +742,7 @@ export class HaConfigDevicePage extends LitElement { type: "logo", darkOptimized: this.hass.themes?.darkMode, })} + crossorigin="anonymous" referrerpolicy="no-referrer" @load=${this._onImageLoad} @error=${this._onImageError} diff --git a/src/panels/config/devices/ha-config-devices-dashboard.ts b/src/panels/config/devices/ha-config-devices-dashboard.ts index 0526d048d11f..6922420986d4 100644 --- a/src/panels/config/devices/ha-config-devices-dashboard.ts +++ b/src/panels/config/devices/ha-config-devices-dashboard.ts @@ -298,6 +298,7 @@ export class HaConfigDeviceDashboard extends LitElement { device.domains.length ? html`
- ${imageURL ? html`` : ""} + ${imageURL + ? html`` + : ""}

${boardName || diff --git a/src/panels/config/helpers/dialog-helper-detail.ts b/src/panels/config/helpers/dialog-helper-detail.ts index 76efa6e17e06..24fdeddf6025 100644 --- a/src/panels/config/helpers/dialog-helper-detail.ts +++ b/src/panels/config/helpers/dialog-helper-detail.ts @@ -207,13 +207,14 @@ export class DialogHelperDetail extends LitElement { ${label} diff --git a/src/panels/config/integrations/ha-config-integration-page.ts b/src/panels/config/integrations/ha-config-integration-page.ts index ab9bab716620..356beed9834e 100644 --- a/src/panels/config/integrations/ha-config-integration-page.ts +++ b/src/panels/config/integrations/ha-config-integration-page.ts @@ -261,6 +261,7 @@ class HaConfigIntegrationPage extends SubscribeMixin(LitElement) { type: "logo", darkOptimized: this.hass.themes?.darkMode, })} + crossorigin="anonymous" referrerpolicy="no-referrer" @load=${this._onImageLoad} @error=${this._onImageError} diff --git a/src/panels/config/integrations/ha-domain-integrations.ts b/src/panels/config/integrations/ha-domain-integrations.ts index ed4fc8c160f5..1e02285c6011 100644 --- a/src/panels/config/integrations/ha-domain-integrations.ts +++ b/src/panels/config/integrations/ha-domain-integrations.ts @@ -61,6 +61,7 @@ class HaDomainIntegrations extends LitElement { useFallback: true, darkOptimized: this.hass.themes?.darkMode, })} + crossorigin="anonymous" referrerpolicy="no-referrer" /> `; diff --git a/src/panels/config/integrations/integration-panels/thread/thread-config-panel.ts b/src/panels/config/integrations/integration-panels/thread/thread-config-panel.ts index 95624b377e2a..731edf7b1a3a 100644 --- a/src/panels/config/integrations/integration-panels/thread/thread-config-panel.ts +++ b/src/panels/config/integrations/integration-panels/thread/thread-config-panel.ts @@ -183,6 +183,7 @@ export class ThreadConfigPanel extends SubscribeMixin(LitElement) { darkOptimized: this.hass.themes?.darkMode, })} alt=${router.brand} + crossorigin="anonymous" referrerpolicy="no-referrer" @error=${this._onImageError} @load=${this._onImageLoad} diff --git a/src/panels/config/repairs/ha-config-repairs.ts b/src/panels/config/repairs/ha-config-repairs.ts index 1643de6b06a0..5295a942d0b6 100644 --- a/src/panels/config/repairs/ha-config-repairs.ts +++ b/src/panels/config/repairs/ha-config-repairs.ts @@ -60,6 +60,7 @@ class HaConfigRepairs extends LitElement { darkOptimized: this.hass.themes?.darkMode, })} .title=${domainToName(this.hass.localize, issue.domain)} + crossorigin="anonymous" referrerpolicy="no-referrer" slot="graphic" /> diff --git a/src/panels/config/repairs/integrations-startup-time.ts b/src/panels/config/repairs/integrations-startup-time.ts index ddb7a4c89ec0..d72ea6eab3e1 100644 --- a/src/panels/config/repairs/integrations-startup-time.ts +++ b/src/panels/config/repairs/integrations-startup-time.ts @@ -72,6 +72,7 @@ class IntegrationsStartupTime extends LitElement { useFallback: true, darkOptimized: this.hass.themes?.darkMode, })} + crossorigin="anonymous" referrerpolicy="no-referrer" slot="graphic" /> diff --git a/src/panels/config/voice-assistants/assist-pref.ts b/src/panels/config/voice-assistants/assist-pref.ts index f38173e84f03..7a39414f94a8 100644 --- a/src/panels/config/voice-assistants/assist-pref.ts +++ b/src/panels/config/voice-assistants/assist-pref.ts @@ -69,6 +69,7 @@ export class AssistPref extends LitElement { type: "icon", darkOptimized: this.hass.themes?.darkMode, })} + crossorigin="anonymous" referrerpolicy="no-referrer" />Assist diff --git a/src/panels/config/voice-assistants/cloud-alexa-pref.ts b/src/panels/config/voice-assistants/cloud-alexa-pref.ts index 2e3f507a6449..22d68687b485 100644 --- a/src/panels/config/voice-assistants/cloud-alexa-pref.ts +++ b/src/panels/config/voice-assistants/cloud-alexa-pref.ts @@ -67,6 +67,7 @@ export class CloudAlexaPref extends LitElement { type: "icon", darkOptimized: this.hass.themes?.darkMode, })} + crossorigin="anonymous" referrerpolicy="no-referrer" />${this.hass.localize("ui.panel.config.cloud.account.alexa.title")} diff --git a/src/panels/config/voice-assistants/cloud-discover.ts b/src/panels/config/voice-assistants/cloud-discover.ts index 581ee0041e41..c8eff2db54f1 100644 --- a/src/panels/config/voice-assistants/cloud-discover.ts +++ b/src/panels/config/voice-assistants/cloud-discover.ts @@ -54,6 +54,7 @@ export class CloudDiscover extends LitElement { type: "icon", darkOptimized: this.hass.themes?.darkMode, })} + crossorigin="anonymous" referrerpolicy="no-referrer" />

diff --git a/src/panels/config/voice-assistants/cloud-google-pref.ts b/src/panels/config/voice-assistants/cloud-google-pref.ts index dfe3b263de8d..027de5628590 100644 --- a/src/panels/config/voice-assistants/cloud-google-pref.ts +++ b/src/panels/config/voice-assistants/cloud-google-pref.ts @@ -72,6 +72,7 @@ export class CloudGooglePref extends LitElement { type: "icon", darkOptimized: this.hass.themes?.darkMode, })} + crossorigin="anonymous" referrerpolicy="no-referrer" />${this.hass.localize("ui.panel.config.cloud.account.google.title")} diff --git a/src/panels/config/voice-assistants/entity-voice-settings.ts b/src/panels/config/voice-assistants/entity-voice-settings.ts index 95d129c4a783..191f5a58b1c8 100644 --- a/src/panels/config/voice-assistants/entity-voice-settings.ts +++ b/src/panels/config/voice-assistants/entity-voice-settings.ts @@ -225,6 +225,7 @@ export class EntityVoiceSettings extends SubscribeMixin(LitElement) { type: "icon", darkOptimized: this.hass.themes?.darkMode, })} + crossorigin="anonymous" referrerpolicy="no-referrer" slot="prefix" /> diff --git a/src/panels/config/voice-assistants/expose/expose-assistant-icon.ts b/src/panels/config/voice-assistants/expose/expose-assistant-icon.ts index 527414b3c9a7..56a384528827 100644 --- a/src/panels/config/voice-assistants/expose/expose-assistant-icon.ts +++ b/src/panels/config/voice-assistants/expose/expose-assistant-icon.ts @@ -37,6 +37,7 @@ export class VoiceAssistantExposeAssistantIcon extends LitElement { type: "icon", darkOptimized: this.hass.themes?.darkMode, })} + crossorigin="anonymous" referrerpolicy="no-referrer" slot="prefix" />