diff --git a/build-scripts/list-plugins-and-polyfills.js b/build-scripts/list-plugins-and-polyfills.js
new file mode 100755
index 0000000000..a0978e6dba
--- /dev/null
+++ b/build-scripts/list-plugins-and-polyfills.js
@@ -0,0 +1,59 @@
+#!/usr/bin/env node
+// Script to print Babel plugins and Core JS polyfills that will be used by browserslist environments
+
+import { version as babelVersion } from "@babel/core";
+import presetEnv from "@babel/preset-env";
+import compilationTargets from "@babel/helper-compilation-targets";
+import coreJSCompat from "core-js-compat";
+import { logPlugin } from "@babel/preset-env/lib/debug.js";
+import { babelOptions } from "./bundle.cjs";
+
+const detailsOpen = (heading) =>
+ `\n${heading}
\n`;
+const detailsClose = " \n";
+
+const dummyAPI = {
+ version: babelVersion,
+ assertVersion: () => {},
+ caller: (callback) =>
+ callback({
+ name: "Dummy Bundler",
+ supportsStaticESM: true,
+ supportsDynamicImport: true,
+ supportsTopLevelAwait: true,
+ supportsExportNamespaceFrom: true,
+ }),
+ targets: () => ({}),
+};
+
+for (const buildType of ["Modern", "Legacy"]) {
+ const browserslistEnv = buildType.toLowerCase();
+ const babelOpts = babelOptions({ latestBuild: browserslistEnv === "modern" });
+ const presetEnvOpts = babelOpts.presets[0][1];
+
+ // Invoking preset-env in debug mode will log the included plugins
+ console.log(detailsOpen(`${buildType} Build Babel Plugins`));
+ presetEnv.default(dummyAPI, {
+ ...presetEnvOpts,
+ browserslistEnv,
+ debug: true,
+ });
+ console.log(detailsClose);
+
+ // Manually log the Core-JS polyfills using the same technique
+ if (presetEnvOpts.useBuiltIns) {
+ console.log(detailsOpen(`${buildType} Build Core-JS Polyfills`));
+ const targets = compilationTargets.default(babelOpts?.targets, {
+ browserslistEnv,
+ });
+ const polyfillList = coreJSCompat({ targets }).list;
+ console.log(
+ "The following %i polyfills may be injected by Babel:\n",
+ polyfillList.length
+ );
+ for (const polyfill of polyfillList) {
+ logPlugin(polyfill, targets, coreJSCompat.data);
+ }
+ console.log(detailsClose);
+ }
+}
diff --git a/build-scripts/list-preset-env-plugins.js b/build-scripts/list-preset-env-plugins.js
deleted file mode 100755
index 5e869a4ef1..0000000000
--- a/build-scripts/list-preset-env-plugins.js
+++ /dev/null
@@ -1,30 +0,0 @@
-#!/usr/bin/env node
-// Script to print Babel plugins that will be used by browserslist environments
-
-import { version as babelVersion } from "@babel/core";
-import presetEnv from "@babel/preset-env";
-import { babelOptions } from "./bundle.cjs";
-
-const dummyAPI = {
- version: babelVersion,
- assertVersion: () => {},
- caller: (callback) =>
- callback({
- name: "Dummy Bundler",
- supportsStaticESM: true,
- supportsDynamicImport: true,
- supportsTopLevelAwait: true,
- supportsExportNamespaceFrom: true,
- }),
- targets: () => ({}),
-};
-
-for (const browserslistEnv of ["modern", "legacy"]) {
- console.log("\nBrowsersList Environment = %s\n", browserslistEnv);
- presetEnv.default(dummyAPI, {
- ...babelOptions({ latestBuild: browserslistEnv === "modern" })
- .presets[0][1],
- browserslistEnv,
- debug: true,
- });
-}
diff --git a/pyproject.toml b/pyproject.toml
index bb03d7594a..38974e1400 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project]
name = "home-assistant-frontend"
-version = "20230428.0"
+version = "20230501.0"
license = {text = "Apache-2.0"}
description = "The Home Assistant frontend"
readme = "README.md"
diff --git a/src/dialogs/voice-command-dialog/ha-voice-command-dialog.ts b/src/dialogs/voice-command-dialog/ha-voice-command-dialog.ts
index ae97087550..87ea70b4e5 100644
--- a/src/dialogs/voice-command-dialog/ha-voice-command-dialog.ts
+++ b/src/dialogs/voice-command-dialog/ha-voice-command-dialog.ts
@@ -401,6 +401,7 @@ export class HaVoiceCommandDialog extends LitElement {
}
});
}
+ this._stt_binary_handler_id = undefined;
this._audioBuffer = [];
const userMessage: Message = {
who: "user",
@@ -463,6 +464,7 @@ export class HaVoiceCommandDialog extends LitElement {
}
if (event.type === "run-end") {
+ this._stt_binary_handler_id = undefined;
unsub();
}
@@ -509,6 +511,7 @@ export class HaVoiceCommandDialog extends LitElement {
}
// Send empty message to indicate we're done streaming.
this._sendAudioChunk(new Int16Array());
+ this._stt_binary_handler_id = undefined;
}
this._audioBuffer = undefined;
}
diff --git a/src/panels/calendar/dialog-calendar-event-editor.ts b/src/panels/calendar/dialog-calendar-event-editor.ts
index 35660d67ae..f6980ba76d 100644
--- a/src/panels/calendar/dialog-calendar-event-editor.ts
+++ b/src/panels/calendar/dialog-calendar-event-editor.ts
@@ -498,12 +498,22 @@ class DialogCalendarEventEditor extends LitElement {
this._submitting = false;
return;
}
+ const eventData = this._calculateData();
+ if (eventData.rrule && range === RecurrenceRange.THISEVENT) {
+ // Updates to a single instance of a recurring event by definition
+ // cannot change the recurrence rule and doing so would be invalid.
+ // It is difficult to detect if the user changed the recurrence rule
+ // since updating the date may change it implicitly (e.g. day of week
+ // of the event changes) so we just assume the users intent based on
+ // recurrence range and drop any other rrule changes.
+ eventData.rrule = undefined;
+ }
try {
await updateCalendarEvent(
this.hass!,
this._calendarId!,
entry.uid!,
- this._calculateData(),
+ eventData,
entry.recurrence_id || "",
range!
);
diff --git a/src/panels/config/voice-assistants/dialog-voice-assistant-pipeline-detail.ts b/src/panels/config/voice-assistants/dialog-voice-assistant-pipeline-detail.ts
index 89f1222fe8..aa221e8b66 100644
--- a/src/panels/config/voice-assistants/dialog-voice-assistant-pipeline-detail.ts
+++ b/src/panels/config/voice-assistants/dialog-voice-assistant-pipeline-detail.ts
@@ -49,10 +49,10 @@ export class DialogVoiceAssistantPipelineDetail extends LitElement {
public showDialog(params: VoiceAssistantPipelineDetailsDialogParams): void {
this._params = params;
this._error = undefined;
+ this._cloudActive = this._params.cloudActiveSubscription;
if (this._params.pipeline) {
this._data = this._params.pipeline;
this._preferred = this._params.preferred;
- this._cloudActive = this._params.cloudActiveSubscription;
} else {
this._data = {
language: (
diff --git a/src/panels/config/voice-assistants/entity-voice-settings.ts b/src/panels/config/voice-assistants/entity-voice-settings.ts
index bc5a3b9a8d..b985447260 100644
--- a/src/panels/config/voice-assistants/entity-voice-settings.ts
+++ b/src/panels/config/voice-assistants/entity-voice-settings.ts
@@ -1,3 +1,4 @@
+import { mdiAlertCircle } from "@mdi/js";
import {
css,
CSSResultGroup,
@@ -32,8 +33,8 @@ import {
updateEntityRegistryEntry,
} from "../../../data/entity_registry";
import {
- GoogleEntity,
fetchCloudGoogleEntity,
+ GoogleEntity,
} from "../../../data/google_assistant";
import { exposeEntities, voiceAssistants } from "../../../data/voice";
import { SubscribeMixin } from "../../../mixins/subscribe-mixin";
@@ -223,7 +224,8 @@ export class EntityVoiceSettings extends SubscribeMixin(LitElement) {
/>
${voiceAssistants[key].name}
${!supported
- ? html`
+ ? html`
+
${this.hass.localize(
"ui.dialogs.voice-settings.unsupported"
)}
@@ -379,6 +381,15 @@ export class EntityVoiceSettings extends SubscribeMixin(LitElement) {
ha-checkbox {
--mdc-checkbox-state-layer-size: 40px;
}
+ .unsupported {
+ display: flex;
+ align-items: center;
+ }
+ .unsupported ha-svg-icon {
+ color: var(--error-color);
+ --mdc-icon-size: 16px;
+ margin-right: 4px;
+ }
.header {
margin-top: 8px;
margin-bottom: 4px;
diff --git a/src/panels/lovelace/hui-root.ts b/src/panels/lovelace/hui-root.ts
index 6fda17d966..02b18b6122 100644
--- a/src/panels/lovelace/hui-root.ts
+++ b/src/panels/lovelace/hui-root.ts
@@ -1063,7 +1063,8 @@ class HUIRoot extends LitElement {
padding-right: env(safe-area-inset-right);
padding-bottom: env(safe-area-inset-bottom);
}
- hui-view {
+ hui-view,
+ hui-unused-entities {
flex: 1 1 100%;
max-width: 100%;
}
diff --git a/src/translations/en.json b/src/translations/en.json
index 23506ac442..fa194a5049 100755
--- a/src/translations/en.json
+++ b/src/translations/en.json
@@ -2761,7 +2761,7 @@
"alert_password_change_required": "You need to change your password before logging in.",
"alert_email_confirm_necessary": "You need to confirm your email before logging in.",
"cloud_pipeline_title": "Want to use Home Assistant Cloud for your voice assistant?",
- "cloud_pipeline_text": "We created a new assistant for you, using the great text-to-speech and speech-to-text engines from Home Assistant Cloud. Would you like to set this assistant as the preferred assistant?"
+ "cloud_pipeline_text": "We created a new assistant for you, using the superior text-to-speech and speech-to-text engines from Home Assistant Cloud. Would you like to set this assistant as the preferred assistant?"
},
"forgot_password": {
"title": "Forgot password",