diff --git a/src/panels/config/cloud/account/cloud-tts-pref.ts b/src/panels/config/cloud/account/cloud-tts-pref.ts
index 2042e6b459..828590f47d 100644
--- a/src/panels/config/cloud/account/cloud-tts-pref.ts
+++ b/src/panels/config/cloud/account/cloud-tts-pref.ts
@@ -23,12 +23,12 @@ import {
updateCloudPref,
} from "../../../../data/cloud";
import type { HomeAssistant } from "../../../../types";
-import { convertTextToSpeech } from "../../../../data/tts";
import { showAlertDialog } from "../../../../dialogs/generic/show-dialog-box";
import { translationMetadata } from "../../../../resources/translations-metadata";
import { caseInsensitiveCompare } from "../../../../common/string/compare";
import memoizeOne from "memoize-one";
import { fireEvent } from "../../../../common/dom/fire_event";
+import { showTryTtsDialog } from "./show-dialog-cloud-tts-try";
@customElement("cloud-tts-pref")
export class CloudTTSPref extends LitElement {
@@ -36,8 +36,6 @@ export class CloudTTSPref extends LitElement {
@property() public cloudStatus?: CloudStatusLoggedIn;
- @internalProperty() private loadingExample = false;
-
@internalProperty() private savingPreferences = false;
@internalProperty() private ttsInfo?: CloudTTSInfo;
@@ -62,12 +60,9 @@ export class CloudTTSPref extends LitElement {
header=${this.hass.localize("ui.panel.config.cloud.account.tts.title")}
>
@@ -191,46 +186,9 @@ export class CloudTTSPref extends LitElement {
}
);
- async _playExample() {
- this.loadingExample = true;
- const defaultVoice = this.cloudStatus!.prefs.tts_default_voice;
- // Our example sentence is English. If user uses English voice, use that
- // for example.
- let language;
- let gender;
- if (defaultVoice[0].split("-")[0] === "en") {
- language = defaultVoice[0];
- gender = defaultVoice[1];
- } else {
- language = "en-US";
- gender = "female";
- }
-
- let url;
- try {
- const result = await convertTextToSpeech(this.hass, {
- platform: "cloud",
- message: `Hello ${
- this.hass.user!.name
- }, you can play any text on any supported media player!`,
- language,
- options: { gender },
- });
- url = result.url;
- } catch (err) {
- this.loadingExample = false;
- // eslint-disable-next-line no-console
- console.error(err);
- showAlertDialog(this, {
- text: `Unable to load example. ${err}`,
- warning: true,
- });
- return;
- }
- const audio = new Audio(url);
- audio.play();
- audio.addEventListener("playing", () => {
- this.loadingExample = false;
+ private _openTryDialog() {
+ showTryTtsDialog(this, {
+ defaultVoice: this.cloudStatus!.prefs.tts_default_voice,
});
}
diff --git a/src/panels/config/cloud/account/dialog-cloud-tts-try.ts b/src/panels/config/cloud/account/dialog-cloud-tts-try.ts
new file mode 100644
index 0000000000..0fb9891aeb
--- /dev/null
+++ b/src/panels/config/cloud/account/dialog-cloud-tts-try.ts
@@ -0,0 +1,201 @@
+import "@material/mwc-button";
+import {
+ css,
+ CSSResult,
+ customElement,
+ html,
+ internalProperty,
+ LitElement,
+ property,
+ query,
+ TemplateResult,
+} from "lit-element";
+import { HomeAssistant } from "../../../../types";
+import { TryTtsDialogParams } from "./show-dialog-cloud-tts-try";
+import { haStyleDialog } from "../../../../resources/styles";
+import { fireEvent } from "../../../../common/dom/fire_event";
+import { convertTextToSpeech } from "../../../../data/tts";
+import { showAlertDialog } from "../../../../dialogs/generic/show-dialog-box";
+import "@polymer/paper-input/paper-textarea";
+import "../../../../components/ha-paper-dropdown-menu";
+import { computeStateDomain } from "../../../../common/entity/compute_state_domain";
+import { computeStateName } from "../../../../common/entity/compute_state_name";
+import "@polymer/paper-item/paper-item";
+import "@polymer/paper-listbox/paper-listbox";
+import { supportsFeature } from "../../../../common/entity/supports-feature";
+import { SUPPORT_PLAY_MEDIA } from "../../../../data/media-player";
+import { createCloseHeading } from "../../../../components/ha-dialog";
+import { mdiPlayCircleOutline } from "@mdi/js";
+import type { PaperListboxElement } from "@polymer/paper-listbox/paper-listbox";
+import type { PaperTextareaElement } from "@polymer/paper-input/paper-textarea";
+import { LocalStorage } from "../../../../common/decorators/local-storage";
+
+@customElement("dialog-cloud-try-tts")
+export class DialogTryTts extends LitElement {
+ @property({ attribute: false }) public hass!: HomeAssistant;
+
+ @internalProperty() private _loadingExample = false;
+
+ @internalProperty() private _params?: TryTtsDialogParams;
+
+ @query("#target") private _targetInput?: PaperListboxElement;
+
+ @query("#message") private _messageInput?: PaperTextareaElement;
+
+ @LocalStorage("cloudTtsTryMessage") private _message?: string;
+
+ @LocalStorage("cloudTtsTryTarget") private _target?: string;
+
+ public showDialog(params: TryTtsDialogParams) {
+ this._params = params;
+ }
+
+ public closeDialog() {
+ this._params = undefined;
+ fireEvent(this, "dialog-closed", { dialog: this.localName });
+ }
+
+ protected render(): TemplateResult {
+ if (!this._params) {
+ return html``;
+ }
+ return html`
+
+
+
+
+
+
+
+
+ ${this.hass.localize(
+ "ui.panel.config.cloud.account.tts.dialog.target_browser"
+ )}
+
+ ${Object.values(this.hass.states)
+ .filter(
+ (entity) =>
+ computeStateDomain(entity) === "media_player" &&
+ supportsFeature(entity, SUPPORT_PLAY_MEDIA)
+ )
+ .map(
+ (entity) => html`
+
+ ${computeStateName(entity)}
+
+ `
+ )}
+
+
+
+
+
+ ${this.hass.localize(
+ "ui.panel.config.cloud.account.tts.dialog.play"
+ )}
+
+
+ `;
+ }
+
+ private async _playExample() {
+ const target = String(this._targetInput?.selected);
+ const message = this._messageInput?.value;
+
+ if (!message || !target) {
+ return;
+ }
+
+ this._message = message;
+ this._target = target;
+
+ if (target === "browser") {
+ this._playBrowser(message);
+ } else {
+ this.hass.callService("tts", "cloud_say", {
+ entity_id: target,
+ message,
+ });
+ }
+ }
+
+ private async _playBrowser(message: string) {
+ this._loadingExample = true;
+
+ const language = this._params!.defaultVoice[0];
+ const gender = this._params!.defaultVoice[1];
+
+ let url;
+ try {
+ const result = await convertTextToSpeech(this.hass, {
+ platform: "cloud",
+ message,
+ language,
+ options: { gender },
+ });
+ url = result.url;
+ } catch (err) {
+ this._loadingExample = false;
+ showAlertDialog(this, {
+ text: `Unable to load example. ${err.error || err.body || err}`,
+ warning: true,
+ });
+ return;
+ }
+ const audio = new Audio(url);
+ audio.addEventListener("canplaythrough", () => {
+ audio.play();
+ });
+ audio.addEventListener("playing", () => {
+ this._loadingExample = false;
+ });
+ }
+
+ static get styles(): CSSResult[] {
+ return [
+ haStyleDialog,
+ css`
+ ha-dialog {
+ --mdc-dialog-max-width: 500px;
+ }
+ `,
+ ];
+ }
+}
+
+declare global {
+ interface HTMLElementTagNameMap {
+ "dialog-cloud-try-tts": DialogTryTts;
+ }
+}
diff --git a/src/panels/config/cloud/account/show-dialog-cloud-tts-try.ts b/src/panels/config/cloud/account/show-dialog-cloud-tts-try.ts
new file mode 100644
index 0000000000..e1afa19d3d
--- /dev/null
+++ b/src/panels/config/cloud/account/show-dialog-cloud-tts-try.ts
@@ -0,0 +1,18 @@
+import { fireEvent } from "../../../../common/dom/fire_event";
+
+export interface TryTtsDialogParams {
+ defaultVoice: [string, string];
+}
+
+export const loadTryTtsDialog = () => import("./dialog-cloud-tts-try");
+
+export const showTryTtsDialog = (
+ element: HTMLElement,
+ dialogParams: TryTtsDialogParams
+): void => {
+ fireEvent(element, "show-dialog", {
+ dialogTag: "dialog-cloud-try-tts",
+ dialogImport: loadTryTtsDialog,
+ dialogParams,
+ });
+};
diff --git a/src/translations/en.json b/src/translations/en.json
index d969ca9c94..3255368b8c 100755
--- a/src/translations/en.json
+++ b/src/translations/en.json
@@ -1682,7 +1682,15 @@
"info": "Bring personality to your home by having it speak to you by using our Text-to-Speech services. You can use this in automations and scripts by using the {service} service.",
"default_language": "Default language to use",
"male": "Male",
- "female": "Female"
+ "female": "Female",
+ "try": "Try",
+ "dialog": {
+ "header": "Try Text to Speech",
+ "example_message": "Hello {name}, you can play any text on any supported media player!",
+ "target": "Target",
+ "target_browser": "Browser",
+ "play": "Play"
+ }
},
"remote": {
"title": "Remote Control",