diff --git a/setup.cfg b/setup.cfg
index 0b418da16a..fd31a6964f 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,6 +1,6 @@
[metadata]
name = home-assistant-frontend
-version = 20220503.0
+version = 20220504.0
author = The Home Assistant Authors
author_email = hello@home-assistant.io
license = Apache-2.0
diff --git a/src/components/media-player/ha-media-player-browse.ts b/src/components/media-player/ha-media-player-browse.ts
index 5f219bf247..285ebcea54 100644
--- a/src/components/media-player/ha-media-player-browse.ts
+++ b/src/components/media-player/ha-media-player-browse.ts
@@ -1,10 +1,11 @@
+import "@lit-labs/virtualizer";
+import type { LitVirtualizer } from "@lit-labs/virtualizer";
+import { grid } from "@lit-labs/virtualizer/layouts/grid";
import "@material/mwc-button/mwc-button";
import "@material/mwc-list/mwc-list";
import "@material/mwc-list/mwc-list-item";
import { mdiArrowUpRight, mdiPlay, mdiPlus } from "@mdi/js";
import "@polymer/paper-tooltip/paper-tooltip";
-import { grid } from "@lit-labs/virtualizer/layouts/grid";
-import "@lit-labs/virtualizer";
import {
css,
CSSResultGroup,
@@ -21,10 +22,12 @@ import {
state,
} from "lit/decorators";
import { classMap } from "lit/directives/class-map";
+import { styleMap } from "lit/directives/style-map";
import { until } from "lit/directives/until";
import { fireEvent } from "../../common/dom/fire_event";
import { computeRTLDirection } from "../../common/util/compute_rtl";
import { debounce } from "../../common/util/debounce";
+import { getSignedPath } from "../../data/auth";
import type { MediaPlayerItem } from "../../data/media-player";
import {
browseMediaPlayer,
@@ -39,6 +42,7 @@ import { showAlertDialog } from "../../dialogs/generic/show-dialog-box";
import { installResizeObserver } from "../../panels/lovelace/common/install-resize-observer";
import { haStyle } from "../../resources/styles";
import type { HomeAssistant } from "../../types";
+import { brandsUrl, extractDomainFromBrandUrl } from "../../util/brands-url";
import { documentationUrl } from "../../util/documentation-url";
import "../entity/ha-entity-picker";
import "../ha-button-menu";
@@ -49,8 +53,6 @@ import "../ha-icon-button";
import "../ha-svg-icon";
import "./ha-browse-media-tts";
import type { TtsMediaPickedEvent } from "./ha-browse-media-tts";
-import { getSignedPath } from "../../data/auth";
-import { brandsUrl, extractDomainFromBrandUrl } from "../../util/brands-url";
declare global {
interface HASSDomEvents {
@@ -100,6 +102,10 @@ export class HaMediaPlayerBrowse extends LitElement {
@query(".content") private _content?: HTMLDivElement;
+ @query("lit-virtualizer") private _virtualizer?: LitVirtualizer;
+
+ private _observed = false;
+
private _headerOffsetHeight = 0;
private _resizeObserver?: ResizeObserver;
@@ -280,6 +286,19 @@ export class HaMediaPlayerBrowse extends LitElement {
this._animateHeaderHeight();
} else if (changedProps.has("_currentItem")) {
this._setHeaderHeight();
+
+ // This fixes a race condition for resizing of the cards using the grid layout
+ if (this._observed) {
+ return;
+ }
+
+ // @ts-ignore
+ const virtualizer = this._virtualizer?._virtualizer;
+
+ if (virtualizer) {
+ this._observed = true;
+ setTimeout(() => virtualizer._observeMutations(), 0);
+ }
}
}
@@ -477,6 +496,9 @@ export class HaMediaPlayerBrowse extends LitElement {
${currentItem.not_shown
@@ -606,7 +628,6 @@ export class HaMediaPlayerBrowse extends LitElement {
${child.title}
-
`;
};
diff --git a/src/data/update.ts b/src/data/update.ts
index e76a8947a3..f888823d21 100644
--- a/src/data/update.ts
+++ b/src/data/update.ts
@@ -2,8 +2,10 @@ import type {
HassEntities,
HassEntityAttributeBase,
HassEntityBase,
+ HassEvent,
} from "home-assistant-js-websocket";
import { BINARY_STATE_ON } from "../common/const";
+import { computeDomain } from "../common/entity/compute_domain";
import { computeStateDomain } from "../common/entity/compute_state_domain";
import { supportsFeature } from "../common/entity/supports-feature";
import { caseInsensitiveStringCompare } from "../common/string/compare";
@@ -110,15 +112,32 @@ export const checkForEntityUpdates = async (
return;
}
+ let updated = 0;
+
+ const unsubscribeEvents = await hass.connection.subscribeEvents(
+ (event) => {
+ if (computeDomain(event.data.entity_id) === "update") {
+ updated++;
+ showToast(element, {
+ message: hass.localize("ui.panel.config.updates.updates_refreshed", {
+ count: updated,
+ }),
+ });
+ }
+ },
+ "state_changed"
+ );
+
await hass.callService("homeassistant", "update_entity", {
entity_id: entities,
});
- if (filterUpdateEntitiesWithInstall(hass.states).length) {
- showToast(element, {
- message: hass.localize("ui.panel.config.updates.updates_refreshed"),
- });
- } else {
+ // there is no reliable way to know if all the updates are done updating, so we just wait a bit for now...
+ await new Promise((r) => setTimeout(r, 10000));
+
+ unsubscribeEvents();
+
+ if (updated === 0) {
showToast(element, {
message: hass.localize("ui.panel.config.updates.no_new_updates"),
});
diff --git a/src/panels/config/automation/action/ha-automation-action.ts b/src/panels/config/automation/action/ha-automation-action.ts
index 0222b11609..3abbbd7d6e 100644
--- a/src/panels/config/automation/action/ha-automation-action.ts
+++ b/src/panels/config/automation/action/ha-automation-action.ts
@@ -1,3 +1,4 @@
+import deepClone from "deep-clone-simple";
import "@material/mwc-button";
import { css, CSSResultGroup, html, LitElement } from "lit";
import { customElement, property } from "lit/decorators";
@@ -83,7 +84,7 @@ export default class HaAutomationAction extends LitElement {
ev.stopPropagation();
const index = (ev.target as any).index;
fireEvent(this, "value-changed", {
- value: this.actions.concat(this.actions[index]),
+ value: this.actions.concat(deepClone(this.actions[index])),
});
}
diff --git a/src/panels/config/automation/condition/ha-automation-condition.ts b/src/panels/config/automation/condition/ha-automation-condition.ts
index 4cee821b21..de5972e164 100644
--- a/src/panels/config/automation/condition/ha-automation-condition.ts
+++ b/src/panels/config/automation/condition/ha-automation-condition.ts
@@ -1,3 +1,4 @@
+import deepClone from "deep-clone-simple";
import "@material/mwc-button";
import { css, CSSResultGroup, html, LitElement, PropertyValues } from "lit";
import { customElement, property } from "lit/decorators";
@@ -96,7 +97,7 @@ export default class HaAutomationCondition extends LitElement {
ev.stopPropagation();
const index = (ev.target as any).index;
fireEvent(this, "value-changed", {
- value: this.conditions.concat(this.conditions[index]),
+ value: this.conditions.concat(deepClone(this.conditions[index])),
});
}
diff --git a/src/panels/config/automation/trigger/ha-automation-trigger.ts b/src/panels/config/automation/trigger/ha-automation-trigger.ts
index 3d058a83fb..1b359dd83e 100644
--- a/src/panels/config/automation/trigger/ha-automation-trigger.ts
+++ b/src/panels/config/automation/trigger/ha-automation-trigger.ts
@@ -1,3 +1,4 @@
+import deepClone from "deep-clone-simple";
import "@material/mwc-button";
import { css, CSSResultGroup, html, LitElement } from "lit";
import { customElement, property } from "lit/decorators";
@@ -67,7 +68,7 @@ export default class HaAutomationTrigger extends LitElement {
ev.stopPropagation();
const index = (ev.target as any).index;
fireEvent(this, "value-changed", {
- value: this.triggers.concat(this.triggers[index]),
+ value: this.triggers.concat(deepClone(this.triggers[index])),
});
}
diff --git a/src/panels/config/core/ha-config-section-updates.ts b/src/panels/config/core/ha-config-section-updates.ts
index a60d568b2c..e7f11d6318 100644
--- a/src/panels/config/core/ha-config-section-updates.ts
+++ b/src/panels/config/core/ha-config-section-updates.ts
@@ -109,7 +109,11 @@ class HaConfigSectionUpdates extends LitElement {
>
`
: html`
- ${this.hass.localize("ui.panel.config.updates.no_updates")}
+
+ ${this.hass.localize(
+ "ui.panel.config.updates.no_updates"
+ )}
+
`}
@@ -198,6 +202,10 @@ class HaConfigSectionUpdates extends LitElement {
flex-direction: column;
padding: 0;
}
+
+ .no-updates {
+ padding: 16px;
+ }
`;
}
diff --git a/src/panels/config/dashboard/ha-config-updates.ts b/src/panels/config/dashboard/ha-config-updates.ts
index 416b0d9d8d..dcb02c4de4 100644
--- a/src/panels/config/dashboard/ha-config-updates.ts
+++ b/src/panels/config/dashboard/ha-config-updates.ts
@@ -9,6 +9,7 @@ import "../../../components/ha-alert";
import "../../../components/ha-icon-next";
import type { UpdateEntity } from "../../../data/update";
import type { HomeAssistant } from "../../../types";
+import "../../../components/ha-circular-progress";
@customElement("ha-config-updates")
class HaConfigUpdates extends LitElement {
@@ -51,7 +52,18 @@ class HaConfigUpdates extends LitElement {
.title=${entity.attributes.title ||
entity.attributes.friendly_name}
.stateObj=${entity}
+ class=${this.narrow && entity.attributes.in_progress
+ ? "updating"
+ : ""}
>
+ ${this.narrow && entity.attributes.in_progress
+ ? html``
+ : ""}
${entity.attributes.title ||
entity.attributes.friendly_name}
${!this.narrow
- ? html``
+ ? entity.attributes.in_progress
+ ? html``
+ : html``
: ""}
`
@@ -121,6 +139,12 @@ class HaConfigUpdates extends LitElement {
cursor: pointer;
font-size: 16px;
}
+ ha-circular-progress.absolute {
+ position: absolute;
+ }
+ state-badge.updating {
+ opacity: 0.5;
+ }
`,
];
}
diff --git a/src/panels/config/integrations/ha-integration-card.ts b/src/panels/config/integrations/ha-integration-card.ts
index d2790ec98f..40484aa881 100644
--- a/src/panels/config/integrations/ha-integration-card.ts
+++ b/src/panels/config/integrations/ha-integration-card.ts
@@ -52,7 +52,6 @@ import type { ConfigEntryExtended } from "./ha-config-integrations";
import "./ha-integration-header";
const integrationsWithPanel = {
- hassio: "/hassio/dashboard",
mqtt: "/config/mqtt",
zha: "/config/zha/dashboard",
zwave_js: "/config/zwave_js/dashboard",
diff --git a/src/translations/en.json b/src/translations/en.json
index 4255e3aaab..649aea8f90 100755
--- a/src/translations/en.json
+++ b/src/translations/en.json
@@ -1175,7 +1175,7 @@
},
"updates": {
"caption": "Updates",
- "description": "Manage updates of Home Assistant, Add-ons and devices",
+ "description": "Manage updates of Home Assistant, add-ons and devices",
"no_updates": "No updates available",
"no_update_entities": {
"title": "Unable to check for updates",
@@ -1183,7 +1183,7 @@
},
"check_updates": "Check for updates",
"no_new_updates": "No new updates found",
- "updates_refreshed": "Updates refreshed",
+ "updates_refreshed": "{count} {count, plural,\n one {update}\n other {updates}\n} refreshed",
"title": "{count} {count, plural,\n one {update}\n other {updates}\n}",
"unable_to_fetch": "Unable to load updates",
"version_available": "Version {version_available} is available",
@@ -1490,7 +1490,7 @@
},
"core": {
"caption": "General",
- "description": "Name, Timezone and locale settings",
+ "description": "Name, time zone and locale settings",
"section": {
"core": {
"header": "General Configuration",
@@ -3139,7 +3139,7 @@
},
"analytics": {
"caption": "Analytics",
- "description": "Learn how to share data to better the Open Home"
+ "description": "Learn how to share data to improve Home Assistant"
},
"network": {
"caption": "Network",
@@ -3184,11 +3184,11 @@
},
"system_health": {
"caption": "System Health",
- "description": "Status, Stats and Integration startup time",
+ "description": "Status, metrics and integration startup time",
"cpu_usage": "Processor Usage",
"ram_usage": "Memory Usage",
- "core_stats": "Core Stats",
- "supervisor_stats": "Supervisor Stats",
+ "core_stats": "Core Metrics",
+ "supervisor_stats": "Supervisor Metrics",
"integration_start_time": "Integration Startup Time"
},
"system_dashboard": {