mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-27 11:16:35 +00:00
Add simple try tts dialog (#8245)
This commit is contained in:
parent
4f0bb9f6c3
commit
b22455d2a5
@ -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")}
|
||||
>
|
||||
<div class="example">
|
||||
<mwc-button
|
||||
@click=${this._playExample}
|
||||
.disabled=${this.loadingExample}
|
||||
>
|
||||
<mwc-button @click=${this._openTryDialog}>
|
||||
<ha-svg-icon .path=${mdiPlayCircleOutline}></ha-svg-icon>
|
||||
Example
|
||||
${this.hass.localize("ui.panel.config.cloud.account.tts.try")}
|
||||
</mwc-button>
|
||||
</div>
|
||||
<div class="card-content">
|
||||
@ -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,
|
||||
});
|
||||
}
|
||||
|
||||
|
201
src/panels/config/cloud/account/dialog-cloud-tts-try.ts
Normal file
201
src/panels/config/cloud/account/dialog-cloud-tts-try.ts
Normal file
@ -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`
|
||||
<ha-dialog
|
||||
open
|
||||
@closed=${this.closeDialog}
|
||||
scrimClickAction
|
||||
escapeKeyAction
|
||||
.heading=${createCloseHeading(
|
||||
this.hass,
|
||||
this.hass.localize("ui.panel.config.cloud.account.tts.dialog.header")
|
||||
)}
|
||||
>
|
||||
<div>
|
||||
<paper-textarea
|
||||
id="message"
|
||||
label="Message"
|
||||
.value=${this._message ||
|
||||
this.hass.localize(
|
||||
"ui.panel.config.cloud.account.tts.dialog.example_message",
|
||||
"name",
|
||||
this.hass.user!.name
|
||||
)}
|
||||
>
|
||||
</paper-textarea>
|
||||
|
||||
<ha-paper-dropdown-menu
|
||||
.label=${this.hass.localize(
|
||||
"ui.panel.config.cloud.account.tts.dialog.target"
|
||||
)}
|
||||
>
|
||||
<paper-listbox
|
||||
id="target"
|
||||
slot="dropdown-content"
|
||||
attr-for-selected="item-value"
|
||||
.selected=${this._target || "browser"}
|
||||
>
|
||||
<paper-item item-value="browser">
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.cloud.account.tts.dialog.target_browser"
|
||||
)}
|
||||
</paper-item>
|
||||
${Object.values(this.hass.states)
|
||||
.filter(
|
||||
(entity) =>
|
||||
computeStateDomain(entity) === "media_player" &&
|
||||
supportsFeature(entity, SUPPORT_PLAY_MEDIA)
|
||||
)
|
||||
.map(
|
||||
(entity) => html`
|
||||
<paper-item .itemValue=${entity.entity_id}>
|
||||
${computeStateName(entity)}
|
||||
</paper-item>
|
||||
`
|
||||
)}
|
||||
</paper-listbox>
|
||||
</ha-paper-dropdown-menu>
|
||||
</div>
|
||||
<mwc-button
|
||||
slot="primaryAction"
|
||||
@click=${this._playExample}
|
||||
.disabled=${this._loadingExample}
|
||||
>
|
||||
<ha-svg-icon .path=${mdiPlayCircleOutline}></ha-svg-icon>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.cloud.account.tts.dialog.play"
|
||||
)}
|
||||
</mwc-button>
|
||||
</ha-dialog>
|
||||
`;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
18
src/panels/config/cloud/account/show-dialog-cloud-tts-try.ts
Normal file
18
src/panels/config/cloud/account/show-dialog-cloud-tts-try.ts
Normal file
@ -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,
|
||||
});
|
||||
};
|
@ -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",
|
||||
|
Loading…
x
Reference in New Issue
Block a user