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`
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- [[_errorMsg]]
-
-
-
-
-
- `;
- }
-
- 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')]]
-
-
-
-
-
- [[getPlatformName(item)]]
-
-
-
-
-
-
-
-
-
- [[localize('ui.panel.mailbox.empty')]]
-
-
-
-
-
-
-
[[item.caller]]
-
- [[localize('ui.duration.second', 'count', item.duration)]]
-
-
-
- [[item.timestamp]] -
- [[item.message]]
-
-
-
-
-
-
-
- `;
- }
-
- 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;
+ };
+ }
+}