mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-27 19:26:36 +00:00
Cache brand images (#17840)
This commit is contained in:
parent
80112bb662
commit
01f51f3247
@ -112,9 +112,7 @@ export class StateBadge extends LitElement {
|
||||
const stateObj = this.stateObj;
|
||||
|
||||
const iconStyle: { [name: string]: string } = {};
|
||||
const hostStyle: Partial<CSSStyleDeclaration> = {
|
||||
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 {
|
||||
|
@ -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}
|
||||
|
@ -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"
|
||||
/>
|
||||
|
@ -2,8 +2,8 @@
|
||||
// eslint-disable-next-line spaced-comment
|
||||
/// <reference path="../types/service-worker.d.ts" />
|
||||
/* 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();
|
||||
|
@ -23,6 +23,7 @@ class IntegrationBadge extends LitElement {
|
||||
type: "icon",
|
||||
darkOptimized: this.darkOptimizedIcon,
|
||||
})}
|
||||
crossorigin="anonymous"
|
||||
referrerpolicy="no-referrer"
|
||||
/>
|
||||
</div>
|
||||
|
@ -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) {
|
||||
<ha-list-item
|
||||
twoline
|
||||
graphic="medium"
|
||||
class=${entity.attributes.skipped_version ? "skipped" : ""}
|
||||
class=${ifDefined(
|
||||
entity.attributes.skipped_version ? "skipped" : undefined
|
||||
)}
|
||||
.entity_id=${entity.entity_id}
|
||||
.hasMeta=${!this.narrow}
|
||||
@click=${this._openMoreInfo}
|
||||
@ -97,9 +100,11 @@ class HaConfigUpdates extends SubscribeMixin(LitElement) {
|
||||
.title=${entity.attributes.title ||
|
||||
entity.attributes.friendly_name}
|
||||
.stateObj=${entity}
|
||||
class=${this.narrow && entity.attributes.in_progress
|
||||
? "updating"
|
||||
: ""}
|
||||
class=${ifDefined(
|
||||
this.narrow && entity.attributes.in_progress
|
||||
? "updating"
|
||||
: undefined
|
||||
)}
|
||||
></state-badge>
|
||||
${this.narrow && entity.attributes.in_progress
|
||||
? html`<ha-circular-progress
|
||||
|
@ -353,6 +353,7 @@ export class HaConfigDevicePage extends LitElement {
|
||||
type: "icon",
|
||||
darkOptimized: this.hass.themes?.darkMode,
|
||||
})}
|
||||
crossorigin="anonymous"
|
||||
referrerpolicy="no-referrer"
|
||||
/>
|
||||
|
||||
@ -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}
|
||||
|
@ -298,6 +298,7 @@ export class HaConfigDeviceDashboard extends LitElement {
|
||||
device.domains.length
|
||||
? html`<img
|
||||
alt=""
|
||||
crossorigin="anonymous"
|
||||
referrerpolicy="no-referrer"
|
||||
src=${brandsUrl({
|
||||
domain: device.domains[0],
|
||||
|
@ -221,6 +221,7 @@ export class EnergyGridSettings extends LitElement {
|
||||
? html`<div class="row" .entry=${this._co2ConfigEntry}>
|
||||
<img
|
||||
alt=""
|
||||
crossorigin="anonymous"
|
||||
referrerpolicy="no-referrer"
|
||||
src=${brandsUrl({
|
||||
domain: "co2signal",
|
||||
@ -246,6 +247,7 @@ export class EnergyGridSettings extends LitElement {
|
||||
<div class="row border-bottom">
|
||||
<img
|
||||
alt=""
|
||||
crossorigin="anonymous"
|
||||
referrerpolicy="no-referrer"
|
||||
src=${brandsUrl({
|
||||
domain: "co2signal",
|
||||
|
@ -155,6 +155,7 @@ export class DialogEnergySolarSettings
|
||||
>
|
||||
<img
|
||||
alt=""
|
||||
crossorigin="anonymous"
|
||||
referrerpolicy="no-referrer"
|
||||
style="height: 24px; margin-right: 16px;"
|
||||
src=${brandsUrl({
|
||||
|
@ -282,7 +282,14 @@ class HaConfigHardware extends SubscribeMixin(LitElement) {
|
||||
? html`
|
||||
<ha-card outlined>
|
||||
<div class="card-content">
|
||||
${imageURL ? html`<img alt="" src=${imageURL} />` : ""}
|
||||
${imageURL
|
||||
? html`<img
|
||||
alt=""
|
||||
src=${imageURL}
|
||||
crossorigin="anonymous"
|
||||
referrerpolicy="no-referrer"
|
||||
/>`
|
||||
: ""}
|
||||
<div class="board-info">
|
||||
<p class="primary-text">
|
||||
${boardName ||
|
||||
|
@ -207,13 +207,14 @@ export class DialogHelperDetail extends LitElement {
|
||||
<img
|
||||
slot="graphic"
|
||||
loading="lazy"
|
||||
alt=""
|
||||
src=${brandsUrl({
|
||||
domain,
|
||||
type: "icon",
|
||||
useFallback: true,
|
||||
darkOptimized: this.hass.themes?.darkMode,
|
||||
})}
|
||||
aria-hidden="true"
|
||||
crossorigin="anonymous"
|
||||
referrerpolicy="no-referrer"
|
||||
/>
|
||||
<span class="item-text"> ${label} </span>
|
||||
|
@ -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}
|
||||
|
@ -61,6 +61,7 @@ class HaDomainIntegrations extends LitElement {
|
||||
useFallback: true,
|
||||
darkOptimized: this.hass.themes?.darkMode,
|
||||
})}
|
||||
crossorigin="anonymous"
|
||||
referrerpolicy="no-referrer"
|
||||
/>
|
||||
<span
|
||||
@ -106,6 +107,7 @@ class HaDomainIntegrations extends LitElement {
|
||||
useFallback: true,
|
||||
darkOptimized: this.hass.themes?.darkMode,
|
||||
})}
|
||||
crossorigin="anonymous"
|
||||
referrerpolicy="no-referrer"
|
||||
/>
|
||||
<span
|
||||
@ -168,6 +170,7 @@ class HaDomainIntegrations extends LitElement {
|
||||
useFallback: true,
|
||||
darkOptimized: this.hass.themes?.darkMode,
|
||||
})}
|
||||
crossorigin="anonymous"
|
||||
referrerpolicy="no-referrer"
|
||||
/>
|
||||
<span
|
||||
|
@ -35,6 +35,7 @@ export class HaIntegrationActionCard extends LitElement {
|
||||
type: "icon",
|
||||
darkOptimized: this.hass.themes?.darkMode,
|
||||
})}
|
||||
crossorigin="anonymous"
|
||||
referrerpolicy="no-referrer"
|
||||
@error=${this._onImageError}
|
||||
@load=${this._onImageLoad}
|
||||
|
@ -35,6 +35,7 @@ export class HaIntegrationHeader extends LitElement {
|
||||
type: "icon",
|
||||
darkOptimized: this.hass.themes?.darkMode,
|
||||
})}
|
||||
crossorigin="anonymous"
|
||||
referrerpolicy="no-referrer"
|
||||
@error=${this._onImageError}
|
||||
@load=${this._onImageLoad}
|
||||
|
@ -58,6 +58,7 @@ export class HaIntegrationListItem extends ListItemBase {
|
||||
darkOptimized: this.hass.themes?.darkMode,
|
||||
brand: this.brand,
|
||||
})}
|
||||
crossorigin="anonymous"
|
||||
referrerpolicy="no-referrer"
|
||||
/>
|
||||
</span>`;
|
||||
|
@ -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}
|
||||
|
@ -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"
|
||||
/>
|
||||
|
@ -72,6 +72,7 @@ class IntegrationsStartupTime extends LitElement {
|
||||
useFallback: true,
|
||||
darkOptimized: this.hass.themes?.darkMode,
|
||||
})}
|
||||
crossorigin="anonymous"
|
||||
referrerpolicy="no-referrer"
|
||||
slot="graphic"
|
||||
/>
|
||||
|
@ -69,6 +69,7 @@ export class AssistPref extends LitElement {
|
||||
type: "icon",
|
||||
darkOptimized: this.hass.themes?.darkMode,
|
||||
})}
|
||||
crossorigin="anonymous"
|
||||
referrerpolicy="no-referrer"
|
||||
/>Assist
|
||||
</h1>
|
||||
|
@ -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")}
|
||||
</h1>
|
||||
|
@ -54,6 +54,7 @@ export class CloudDiscover extends LitElement {
|
||||
type: "icon",
|
||||
darkOptimized: this.hass.themes?.darkMode,
|
||||
})}
|
||||
crossorigin="anonymous"
|
||||
referrerpolicy="no-referrer"
|
||||
/>
|
||||
<img
|
||||
@ -63,6 +64,7 @@ export class CloudDiscover extends LitElement {
|
||||
type: "icon",
|
||||
darkOptimized: this.hass.themes?.darkMode,
|
||||
})}
|
||||
crossorigin="anonymous"
|
||||
referrerpolicy="no-referrer"
|
||||
/>
|
||||
</div>
|
||||
|
@ -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")}
|
||||
</h1>
|
||||
|
@ -225,6 +225,7 @@ export class EntityVoiceSettings extends SubscribeMixin(LitElement) {
|
||||
type: "icon",
|
||||
darkOptimized: this.hass.themes?.darkMode,
|
||||
})}
|
||||
crossorigin="anonymous"
|
||||
referrerpolicy="no-referrer"
|
||||
slot="prefix"
|
||||
/>
|
||||
|
@ -37,6 +37,7 @@ export class VoiceAssistantExposeAssistantIcon extends LitElement {
|
||||
type: "icon",
|
||||
darkOptimized: this.hass.themes?.darkMode,
|
||||
})}
|
||||
crossorigin="anonymous"
|
||||
referrerpolicy="no-referrer"
|
||||
slot="prefix"
|
||||
/>
|
||||
|
Loading…
x
Reference in New Issue
Block a user