From e06bd41b5ed67c0460eb20e7e16dfa6d7c12a5ad Mon Sep 17 00:00:00 2001 From: Simon Lamon <32477463+silamon@users.noreply.github.com> Date: Wed, 30 Aug 2023 15:21:20 +0200 Subject: [PATCH] Migrate mailbox to LitElement (#17690) * migrate mailbox to lit * Make some methods private * Clean up --- .../mailbox/ha-dialog-show-audio-message.js | 158 ---------- .../mailbox/ha-dialog-show-audio-message.ts | 153 ++++++++++ src/panels/mailbox/ha-panel-mailbox.js | 251 ---------------- src/panels/mailbox/ha-panel-mailbox.ts | 282 ++++++++++++++++++ 4 files changed, 435 insertions(+), 409 deletions(-) delete mode 100644 src/panels/mailbox/ha-dialog-show-audio-message.js create mode 100644 src/panels/mailbox/ha-dialog-show-audio-message.ts delete mode 100644 src/panels/mailbox/ha-panel-mailbox.js create mode 100644 src/panels/mailbox/ha-panel-mailbox.ts diff --git a/src/panels/mailbox/ha-dialog-show-audio-message.js b/src/panels/mailbox/ha-dialog-show-audio-message.js deleted file mode 100644 index 8c199763f9..0000000000 --- a/src/panels/mailbox/ha-dialog-show-audio-message.js +++ /dev/null @@ -1,158 +0,0 @@ -import "@material/mwc-button"; -import { html } from "@polymer/polymer/lib/utils/html-tag"; -/* eslint-plugin-disable lit */ -import { PolymerElement } from "@polymer/polymer/polymer-element"; -import "../../components/ha-dialog"; -import "../../components/ha-circular-progress"; -import "../../components/ha-icon"; -import "../../components/ha-icon-button"; -import LocalizeMixin from "../../mixins/localize-mixin"; -import "../../styles/polymer-ha-style-dialog"; - -/* - * @appliesMixin LocalizeMixin - */ -class HaDialogShowAudioMessage extends LocalizeMixin(PolymerElement) { - static get template() { - return html` - - -
-
- - - - -
-
-
- - -
-
-
- `; - } - - static get properties() { - return { - hass: Object, - - _currentMessage: Object, - - // Error message when can't talk to server etc - _errorMsg: String, - - _loading: { - type: Boolean, - value: false, - }, - - _opened: { - type: Boolean, - value: false, - }, - }; - } - - showDialog({ hass, message }) { - this.hass = hass; - this._errorMsg = null; - this._currentMessage = message; - this._opened = true; - this.$.transcribe.innerText = message.message; - const platform = message.platform; - const mp3 = this.$.mp3; - if (platform.has_media) { - mp3.style.display = ""; - this._showLoading(true); - mp3.src = null; - const url = `/api/mailbox/media/${platform.name}/${message.sha}`; - this.hass - .fetchWithAuth(url) - .then((response) => { - if (response.ok) { - return response.blob(); - } - return Promise.reject({ - status: response.status, - statusText: response.statusText, - }); - }) - .then((blob) => { - this._showLoading(false); - mp3.src = window.URL.createObjectURL(blob); - mp3.play(); - }) - .catch((err) => { - this._showLoading(false); - this._errorMsg = `Error loading audio: ${err.statusText}`; - }); - } else { - mp3.style.display = "none"; - this._showLoading(false); - } - } - - openDeleteDialog() { - if (confirm(this.localize("ui.panel.mailbox.delete_prompt"))) { - this.deleteSelected(); - } - } - - deleteSelected() { - const msg = this._currentMessage; - this.hass.callApi( - "DELETE", - `mailbox/delete/${msg.platform.name}/${msg.sha}` - ); - this._dialogDone(); - } - - _dialogDone() { - this.$.mp3.pause(); - this.setProperties({ - _currentMessage: null, - _errorMsg: null, - _loading: false, - _opened: false, - }); - } - - closeDialog() { - this._dialogDone(); - } - - _showLoading(displayed) { - const delicon = this.$.delicon; - if (displayed) { - this._loading = true; - delicon.style.display = "none"; - } else { - const platform = this._currentMessage.platform; - this._loading = false; - delicon.style.display = platform.can_delete ? "" : "none"; - } - } -} -customElements.define("ha-dialog-show-audio-message", HaDialogShowAudioMessage); diff --git a/src/panels/mailbox/ha-dialog-show-audio-message.ts b/src/panels/mailbox/ha-dialog-show-audio-message.ts new file mode 100644 index 0000000000..c7ad876bfe --- /dev/null +++ b/src/panels/mailbox/ha-dialog-show-audio-message.ts @@ -0,0 +1,153 @@ +import "@material/mwc-button"; +import "../../components/ha-dialog"; +import "../../components/ha-circular-progress"; +import "../../components/ha-icon"; +import "../../components/ha-icon-button"; +import { + CSSResultGroup, + LitElement, + TemplateResult, + css, + html, + nothing, +} from "lit"; +import { customElement, property, state } from "lit/decorators"; +import { HomeAssistant } from "../../types"; +import { haStyleDialog } from "../../resources/styles"; + +@customElement("ha-dialog-show-audio-message") +class HaDialogShowAudioMessage extends LitElement { + @property({ attribute: false }) public hass!: HomeAssistant; + + @state() private _currentMessage?: any; + + @state() private _errorMsg?: string; + + @state() private _loading: boolean = false; + + @state() private _opened: boolean = false; + + @state() private _blobUrl?: string; + + protected render(): TemplateResult { + return html` + + ${this._loading + ? html`` + : html`
+ + + +
+ ${ + this._currentMessage + ? html`
+ ${this._currentMessage?.message} +
` + : nothing + } + ${ + this._errorMsg + ? html`
${this._errorMsg}
` + : nothing + } + ${ + this._blobUrl + ? html` ` + : nothing + } + `} +
+ `; + } + + showDialog({ hass, message }) { + this.hass = hass; + this._errorMsg = undefined; + this._currentMessage = message; + this._opened = true; + const platform = message.platform; + if (platform.has_media) { + this._loading = true; + const url = `/api/mailbox/media/${platform.name}/${message.sha}`; + this.hass + .fetchWithAuth(url) + .then((response) => { + if (response.ok) { + return response.blob(); + } + return Promise.reject({ + status: response.status, + statusText: response.statusText, + }); + }) + .then((blob) => { + this._loading = false; + this._blobUrl = window.URL.createObjectURL(blob); + }) + .catch((err) => { + this._loading = false; + this._errorMsg = `Error loading audio: ${err.statusText}`; + }); + } else { + this._loading = false; + } + } + + private _openDeleteDialog() { + if (confirm(this.hass.localize("ui.panel.mailbox.delete_prompt"))) { + this._deleteSelected(); + } + } + + private _deleteSelected() { + const msg = this._currentMessage; + this.hass.callApi( + "DELETE", + `mailbox/delete/${msg.platform.name}/${msg.sha}` + ); + this._closeDialog(); + } + + private _closeDialog() { + const mp3 = this.shadowRoot!.querySelector("#mp3")! as any; + mp3.pause(); + this._currentMessage = undefined; + this._errorMsg = undefined; + this._loading = false; + this._opened = false; + } + + static get styles(): CSSResultGroup { + return [ + haStyleDialog, + css` + .error { + color: red; + } + p { + color: var(--secondary-text-color); + } + .icon { + text-align: var(--float-end); + } + `, + ]; + } +} + +declare global { + interface HTMLElementTagNameMap { + "ha-dialog-show-audio-message": HaDialogShowAudioMessage; + } +} diff --git a/src/panels/mailbox/ha-panel-mailbox.js b/src/panels/mailbox/ha-panel-mailbox.js deleted file mode 100644 index a156196d42..0000000000 --- a/src/panels/mailbox/ha-panel-mailbox.js +++ /dev/null @@ -1,251 +0,0 @@ -import "@material/mwc-button"; -import "@polymer/app-layout/app-header/app-header"; -import "@polymer/app-layout/app-toolbar/app-toolbar"; -import "@polymer/paper-item/paper-item"; -import "@polymer/paper-item/paper-item-body"; -import "@polymer/paper-tabs/paper-tab"; -import { html } from "@polymer/polymer/lib/utils/html-tag"; -/* eslint-plugin-disable lit */ -import { PolymerElement } from "@polymer/polymer/polymer-element"; -import { formatDateTime } from "../../common/datetime/format_date_time"; -import "../../components/ha-card"; -import "../../components/ha-menu-button"; -import "../../components/ha-tabs"; -import "../../layouts/ha-app-layout"; -import { EventsMixin } from "../../mixins/events-mixin"; -import LocalizeMixin from "../../mixins/localize-mixin"; -import "../../styles/polymer-ha-style"; - -let registeredDialog = false; - -/* - * @appliesMixin LocalizeMixin - */ -class HaPanelMailbox extends EventsMixin(LocalizeMixin(PolymerElement)) { - static get template() { - return html` - - - - - - -
[[localize('panel.mailbox')]]
-
-
- - - -
-
-
- - - - -
-
- `; - } - - static get properties() { - return { - hass: Object, - narrow: Boolean, - - platforms: { - type: Array, - }, - - _messages: { - type: Array, - }, - - _currentPlatform: { - type: Number, - value: 0, - }, - }; - } - - connectedCallback() { - super.connectedCallback(); - if (!registeredDialog) { - registeredDialog = true; - this.fire("register-dialog", { - dialogShowEvent: "show-audio-message-dialog", - dialogTag: "ha-dialog-show-audio-message", - dialogImport: () => import("./ha-dialog-show-audio-message"), - }); - } - this.hassChanged = this.hassChanged.bind(this); - this.hass.connection - .subscribeEvents(this.hassChanged, "mailbox_updated") - .then((unsub) => { - this._unsubEvents = unsub; - }); - this.computePlatforms().then((platforms) => { - this.platforms = platforms; - this.hassChanged(); - }); - } - - disconnectedCallback() { - super.disconnectedCallback(); - if (this._unsubEvents) this._unsubEvents(); - } - - hassChanged() { - if (!this._messages) { - this._messages = []; - } - this.getMessages().then((items) => { - this._messages = items; - }); - } - - openMP3Dialog(event) { - this.fire("show-audio-message-dialog", { - hass: this.hass, - message: event.model.item, - }); - } - - getMessages() { - const platform = this.platforms[this._currentPlatform]; - return this.hass - .callApi("GET", `mailbox/messages/${platform.name}`) - .then((values) => { - const platformItems = []; - const arrayLength = values.length; - for (let i = 0; i < arrayLength; i++) { - const datetime = formatDateTime( - new Date(values[i].info.origtime * 1000), - this.hass.locale, - this.hass.config - ); - platformItems.push({ - timestamp: datetime, - caller: values[i].info.callerid, - message: values[i].text, - sha: values[i].sha, - duration: values[i].info.duration, - platform: platform, - }); - } - return platformItems.sort( - (a, b) => new Date(b.timestamp) - new Date(a.timestamp) - ); - }); - } - - computePlatforms() { - return this.hass.callApi("GET", "mailbox/platforms"); - } - - handlePlatformSelected(ev) { - const newPlatform = ev.detail.selected; - if (newPlatform !== this._currentPlatform) { - this._currentPlatform = newPlatform; - this.hassChanged(); - } - } - - areTabsHidden(platforms) { - return !platforms || platforms.length < 2; - } - - getPlatformName(item) { - const entity = `mailbox.${item.name}`; - const stateObj = this.hass.states[entity.toLowerCase()]; - return stateObj.attributes.friendly_name; - } -} - -customElements.define("ha-panel-mailbox", HaPanelMailbox); diff --git a/src/panels/mailbox/ha-panel-mailbox.ts b/src/panels/mailbox/ha-panel-mailbox.ts new file mode 100644 index 0000000000..0d0159902e --- /dev/null +++ b/src/panels/mailbox/ha-panel-mailbox.ts @@ -0,0 +1,282 @@ +import { + CSSResultGroup, + LitElement, + TemplateResult, + css, + html, + nothing, +} from "lit"; +import { customElement, property, state } from "lit/decorators"; +import "@material/mwc-button"; +import { formatDateTime } from "../../common/datetime/format_date_time"; +import "../../components/ha-card"; +import "../../components/ha-menu-button"; +import "../../components/ha-tabs"; +import "../../layouts/ha-app-layout"; +import "@polymer/paper-item/paper-item"; +import "@polymer/paper-item/paper-item-body"; +import "@polymer/paper-tabs/paper-tab"; +import { HomeAssistant } from "../../types"; +import { fireEvent } from "../../common/dom/fire_event"; +import { haStyle } from "../../resources/styles"; +import "../../components/ha-top-app-bar-fixed"; + +let registeredDialog = false; + +interface MailboxMessage { + info: { + origtime: number; + callerid: string; + duration: string; + }; + text: string; + sha: string; +} + +@customElement("ha-panel-mailbox") +class HaPanelMailbox extends LitElement { + @property({ attribute: false }) public hass!: HomeAssistant; + + @property({ attribute: false }) public narrow!: boolean; + + @property({ attribute: false }) public platforms?: any[]; + + @state() private _messages?: any[]; + + @state() private _currentPlatform: number = 0; + + private _unsubEvents?; + + protected render(): TemplateResult { + return html` + + +
${this.hass.localize("panel.mailbox")}
+ ${!this._areTabsHidden(this.platforms) + ? html`
+ + ${this.platforms?.map( + (platform) => + html` + ${this._getPlatformName(platform)} + ` + )} + +
` + : ""} +
+
+ + ${!this._messages?.length + ? html`
+ ${this.hass.localize("ui.panel.mailbox.empty")} +
` + : nothing} + ${this._messages?.map( + (message) => + html` + +
+
${message.caller}
+
+ ${this.hass.localize( + "ui.duration.second", + "count", + message.duration + )} +
+
+
+ ${message.timestamp} - + ${message.message} +
+
+
` + )} +
+
+ `; + } + + connectedCallback() { + super.connectedCallback(); + if (!registeredDialog) { + registeredDialog = true; + fireEvent(this, "register-dialog", { + dialogShowEvent: "show-audio-message-dialog", + dialogTag: "ha-dialog-show-audio-message", + dialogImport: () => import("./ha-dialog-show-audio-message"), + }); + } + this.hassChanged = this.hassChanged.bind(this); + this.hass.connection + .subscribeEvents(this.hassChanged, "mailbox_updated") + .then((unsub) => { + this._unsubEvents = unsub; + }); + this._computePlatforms().then((platforms) => { + this.platforms = platforms; + this.hassChanged(); + }); + } + + disconnectedCallback() { + super.disconnectedCallback(); + if (this._unsubEvents) this._unsubEvents(); + } + + hassChanged() { + if (!this._messages) { + this._messages = []; + } + this._getMessages().then((items) => { + this._messages = items; + }); + } + + private _openMP3Dialog(ev) { + const message: any = (ev.currentTarget! as any).message; + fireEvent(this, "show-audio-message-dialog", { + hass: this.hass, + message: message, + }); + } + + private _getMessages() { + const platform = this.platforms![this._currentPlatform]; + return this.hass + .callApi("GET", `mailbox/messages/${platform.name}`) + .then((values) => { + const platformItems: any[] = []; + const arrayLength = values.length; + for (let i = 0; i < arrayLength; i++) { + const datetime = formatDateTime( + new Date(values[i].info.origtime * 1000), + this.hass.locale, + this.hass.config + ); + platformItems.push({ + timestamp: datetime, + caller: values[i].info.callerid, + message: values[i].text, + sha: values[i].sha, + duration: values[i].info.duration, + platform: platform, + }); + } + return platformItems.sort((a, b) => b.timestamp - a.timestamp); + }); + } + + private _computePlatforms(): Promise { + return this.hass.callApi("GET", "mailbox/platforms"); + } + + private _handlePlatformSelected(ev) { + const newPlatform = ev.detail.selected; + if (newPlatform !== this._currentPlatform) { + this._currentPlatform = newPlatform; + this.hassChanged(); + } + } + + private _areTabsHidden(platforms) { + return !platforms || platforms.length < 2; + } + + private _getPlatformName(item) { + const entity = `mailbox.${item.name}`; + const stateObj = this.hass.states[entity.toLowerCase()]; + return stateObj.attributes.friendly_name; + } + + static get styles(): CSSResultGroup { + return [ + haStyle, + css` + :host { + -ms-user-select: initial; + -webkit-user-select: initial; + -moz-user-select: initial; + } + + .content { + padding: 16px; + max-width: 600px; + margin: 0 auto; + } + + ha-card { + overflow: hidden; + } + + paper-item { + cursor: pointer; + } + + ha-tabs { + margin-left: max(env(safe-area-inset-left), 24px); + margin-right: max(env(safe-area-inset-right), 24px); + --paper-tabs-selection-bar-color: #fff; + text-transform: uppercase; + } + + .empty { + text-align: center; + color: var(--secondary-text-color); + } + + .header { + @apply --paper-font-title; + } + + .row { + display: flex; + justify-content: space-between; + } + + @media all and (max-width: 450px) { + .content { + width: auto; + padding: 0; + } + } + + .tip { + color: var(--secondary-text-color); + font-size: 14px; + } + .date { + color: var(--primary-text-color); + } + `, + ]; + } +} + +declare global { + interface HTMLElementTagNameMap { + "ha-panel-mailbox": HaPanelMailbox; + } +} + +declare global { + // for fire event + interface HASSDomEvents { + "show-audio-message-dialog": { + hass: HomeAssistant; + message: string; + }; + } +}