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 87ea70b4e5..aabdb1e7c4 100644 --- a/src/dialogs/voice-command-dialog/ha-voice-command-dialog.ts +++ b/src/dialogs/voice-command-dialog/ha-voice-command-dialog.ts @@ -1,5 +1,6 @@ import "@material/mwc-button/mwc-button"; import { + mdiAlertCircle, mdiChevronDown, mdiClose, mdiHelpCircleOutline, @@ -14,6 +15,7 @@ import { LitElement, nothing, PropertyValues, + TemplateResult, } from "lit"; import { customElement, property, query, state } from "lit/decorators"; import { LocalStorage } from "../../common/decorators/local-storage"; @@ -42,7 +44,7 @@ import { showAlertDialog } from "../generic/show-dialog-box"; interface Message { who: string; - text?: string; + text?: string | TemplateResult; error?: boolean; } @@ -109,7 +111,10 @@ export class HaVoiceCommandDialog extends LitElement { if (!this._opened) { return nothing; } - const supportsSTT = this._pipeline?.stt_engine && AudioRecorder.isSupported; + + const supportsMicrophone = AudioRecorder.isSupported; + const supportsSTT = this._pipeline?.stt_engine; + return html` ${pipeline.name}${pipeline.id === this._preferredPipeline - ? html`` + ? html` + + ` : nothing} ` )} @@ -203,7 +210,7 @@ export class HaVoiceCommandDialog extends LitElement { iconTrailing > - ${this._showSendButton + ${this._showSendButton || !supportsSTT ? html` ` - : supportsSTT - ? html` + : html` ${this._audioRecorder?.active ? html`
@@ -224,18 +230,27 @@ export class HaVoiceCommandDialog extends LitElement {
` - : ""} - - - ` - : ""} + : nothing} + +
+ + + ${!supportsMicrophone + ? html` + + ` + : null} +
+ `}
${this._agentInfo && this._agentInfo.attribution @@ -382,7 +397,14 @@ export class HaVoiceCommandDialog extends LitElement { } } - private _toggleListening() { + private _toggleListening(ev) { + ev.stopPropagation(); + ev.preventDefault(); + const supportsMicrophone = AudioRecorder.isSupported; + if (!supportsMicrophone) { + this._showNotSupportedMessage(); + return; + } if (!this._audioRecorder?.active) { this._startListening(); } else { @@ -390,6 +412,40 @@ export class HaVoiceCommandDialog extends LitElement { } } + private async _showNotSupportedMessage() { + this._addMessage({ + who: "hass", + text: html` +

+ ${this.hass.localize( + "ui.dialogs.voice_command.not_supported_microphone" + )} +

+

+ ${this.hass.localize( + "ui.dialogs.voice_command.not_supported_microphone_documentation", + { + documentation_link: html` + + ${this.hass.localize( + "ui.dialogs.voice_command.not_supported_microphone_documentation_link" + )} + + `, + } + )} +

+ `, + }); + } + private async _startListening() { this._audio?.pause(); if (!this._audioRecorder) { @@ -561,7 +617,8 @@ export class HaVoiceCommandDialog extends LitElement { return [ haStyleDialog, css` - ha-icon-button.listening-icon { + .listening-icon { + position: relative; color: var(--secondary-text-color); margin-right: -24px; margin-inline-end: -24px; @@ -569,10 +626,18 @@ export class HaVoiceCommandDialog extends LitElement { direction: var(--direction); } - ha-icon-button.listening-icon[active] { + .listening-icon[active] { color: var(--primary-color); } + .unsupported { + color: var(--error-color); + position: absolute; + --mdc-icon-size: 16px; + right: 5px; + top: 0px; + } + ha-dialog { --primary-action-button-flex: 1; --secondary-action-button-flex: 0; @@ -616,6 +681,19 @@ export class HaVoiceCommandDialog extends LitElement { ha-button-menu ha-button ha-svg-icon { height: 28px; margin-left: 4px; + margin-inline-start: 4px; + margin-inline-end: 4px; + direction: var(--direction); + } + ha-list-item { + --mdc-list-item-meta-size: 16px; + } + ha-list-item ha-svg-icon { + margin-left: 4px; + margin-inline-start: 4px; + margin-inline-end: 4px; + direction: var(--direction); + display: block; } ha-button-menu a { text-decoration: none; @@ -648,6 +726,7 @@ export class HaVoiceCommandDialog extends LitElement { display: block; height: 400px; box-sizing: border-box; + position: relative; } @media all and (max-width: 450px), all and (max-height: 500px) { ha-dialog { @@ -655,6 +734,7 @@ export class HaVoiceCommandDialog extends LitElement { } .messages { height: 100%; + flex: 1; } } .messages-container { @@ -674,6 +754,12 @@ export class HaVoiceCommandDialog extends LitElement { padding: 8px; border-radius: 15px; } + .message p { + margin: 0; + } + .message p:not(:last-child) { + margin-bottom: 8px; + } .message.user { margin-left: 24px; diff --git a/src/translations/en.json b/src/translations/en.json index fa194a5049..39ce950ae0 100755 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -838,7 +838,10 @@ "input_label": "Enter a request", "send_text": "Send text", "start_listening": "Start listening", - "manage_assistants": "Manage assistants" + "manage_assistants": "Manage assistants", + "not_supported_microphone": "Microphone is not supported. You need to access Home Assistant from a secure URL (HTTPS) to use it.", + "not_supported_microphone_documentation": "Visit {documentation_link} to learn how to use a secure URL", + "not_supported_microphone_documentation_link": "the documentation" }, "generic": { "cancel": "Cancel",