mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-25 18:26:35 +00:00
Migrate mailbox to LitElement (#17690)
* migrate mailbox to lit * Make some methods private * Clean up
This commit is contained in:
parent
c0793fad83
commit
e06bd41b5e
@ -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`
|
|
||||||
<style include="ha-style-dialog">
|
|
||||||
.error {
|
|
||||||
color: red;
|
|
||||||
}
|
|
||||||
p {
|
|
||||||
color: var(--secondary-text-color);
|
|
||||||
}
|
|
||||||
.icon {
|
|
||||||
text-align: var(--float-end);
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<ha-dialog
|
|
||||||
open="[[_opened]]"
|
|
||||||
on-closed="closeDialog"
|
|
||||||
heading="[[localize('ui.panel.mailbox.playback_title')]]"
|
|
||||||
>
|
|
||||||
<div>
|
|
||||||
<div class="icon">
|
|
||||||
<template is="dom-if" if="[[_loading]]">
|
|
||||||
<ha-circular-progress active></ha-circular-progress>
|
|
||||||
</template>
|
|
||||||
<ha-icon-button id="delicon" on-click="openDeleteDialog">
|
|
||||||
<ha-icon icon="hass:delete"></ha-icon>
|
|
||||||
</ha-icon-button>
|
|
||||||
</div>
|
|
||||||
<div id="transcribe"></div>
|
|
||||||
<div>
|
|
||||||
<template is="dom-if" if="[[_errorMsg]]">
|
|
||||||
<div class="error">[[_errorMsg]]</div>
|
|
||||||
</template>
|
|
||||||
<audio id="mp3" preload="none" controls>
|
|
||||||
<source id="mp3src" src="" type="audio/mpeg" />
|
|
||||||
</audio>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</ha-dialog>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
153
src/panels/mailbox/ha-dialog-show-audio-message.ts
Normal file
153
src/panels/mailbox/ha-dialog-show-audio-message.ts
Normal file
@ -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`
|
||||||
|
<ha-dialog
|
||||||
|
.open=${this._opened}
|
||||||
|
@closed=${this._closeDialog}
|
||||||
|
heading=${this.hass.localize("ui.panel.mailbox.playback_title")}
|
||||||
|
>
|
||||||
|
${this._loading
|
||||||
|
? html`<ha-circular-progress active></ha-circular-progress>`
|
||||||
|
: html`<div class="icon">
|
||||||
|
<ha-icon-button id="delicon" @click=${this._openDeleteDialog}>
|
||||||
|
<ha-icon icon="hass:delete"></ha-icon>
|
||||||
|
</ha-icon-button>
|
||||||
|
</div>
|
||||||
|
${
|
||||||
|
this._currentMessage
|
||||||
|
? html`<div id="transcribe">
|
||||||
|
${this._currentMessage?.message}
|
||||||
|
</div>`
|
||||||
|
: nothing
|
||||||
|
}
|
||||||
|
${
|
||||||
|
this._errorMsg
|
||||||
|
? html`<div class="error">${this._errorMsg}</div>`
|
||||||
|
: nothing
|
||||||
|
}
|
||||||
|
${
|
||||||
|
this._blobUrl
|
||||||
|
? html` <audio id="mp3" preload="none" controls autoplay>
|
||||||
|
<source
|
||||||
|
id="mp3src"
|
||||||
|
src=${this._blobUrl}
|
||||||
|
type="audio/mpeg"
|
||||||
|
/>
|
||||||
|
</audio>`
|
||||||
|
: nothing
|
||||||
|
}
|
||||||
|
</div>`}
|
||||||
|
</ha-dialog>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
@ -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`
|
|
||||||
<style include="ha-style">
|
|
||||||
: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);
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<ha-app-layout>
|
|
||||||
<app-header slot="header" fixed>
|
|
||||||
<app-toolbar>
|
|
||||||
<ha-menu-button
|
|
||||||
hass="[[hass]]"
|
|
||||||
narrow="[[narrow]]"
|
|
||||||
></ha-menu-button>
|
|
||||||
<div main-title>[[localize('panel.mailbox')]]</div>
|
|
||||||
</app-toolbar>
|
|
||||||
<div sticky hidden$="[[areTabsHidden(platforms)]]">
|
|
||||||
<ha-tabs
|
|
||||||
scrollable
|
|
||||||
selected="[[_currentPlatform]]"
|
|
||||||
on-iron-activate="handlePlatformSelected"
|
|
||||||
>
|
|
||||||
<template is="dom-repeat" items="[[platforms]]">
|
|
||||||
<paper-tab data-entity="[[item]]">
|
|
||||||
[[getPlatformName(item)]]
|
|
||||||
</paper-tab>
|
|
||||||
</template>
|
|
||||||
</ha-tabs>
|
|
||||||
</div>
|
|
||||||
</app-header>
|
|
||||||
<div class="content">
|
|
||||||
<ha-card>
|
|
||||||
<template is="dom-if" if="[[!_messages.length]]">
|
|
||||||
<div class="card-content empty">
|
|
||||||
[[localize('ui.panel.mailbox.empty')]]
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<template is="dom-repeat" items="[[_messages]]">
|
|
||||||
<paper-item on-click="openMP3Dialog">
|
|
||||||
<paper-item-body style="width:100%" two-line>
|
|
||||||
<div class="row">
|
|
||||||
<div>[[item.caller]]</div>
|
|
||||||
<div class="tip">
|
|
||||||
[[localize('ui.duration.second', 'count', item.duration)]]
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div secondary>
|
|
||||||
<span class="date">[[item.timestamp]]</span> -
|
|
||||||
[[item.message]]
|
|
||||||
</div>
|
|
||||||
</paper-item-body>
|
|
||||||
</paper-item>
|
|
||||||
</template>
|
|
||||||
</ha-card>
|
|
||||||
</div>
|
|
||||||
</ha-app-layout>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
282
src/panels/mailbox/ha-panel-mailbox.ts
Normal file
282
src/panels/mailbox/ha-panel-mailbox.ts
Normal file
@ -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`
|
||||||
|
<ha-top-app-bar-fixed>
|
||||||
|
<ha-menu-button
|
||||||
|
slot="navigationIcon"
|
||||||
|
.hass=${this.hass}
|
||||||
|
.narrow=${this.narrow}
|
||||||
|
></ha-menu-button>
|
||||||
|
<div slot="title">${this.hass.localize("panel.mailbox")}</div>
|
||||||
|
${!this._areTabsHidden(this.platforms)
|
||||||
|
? html`<div sticky>
|
||||||
|
<ha-tabs
|
||||||
|
scrollable
|
||||||
|
.selected=${this._currentPlatform}
|
||||||
|
@iron-activate=${this._handlePlatformSelected}
|
||||||
|
>
|
||||||
|
${this.platforms?.map(
|
||||||
|
(platform) =>
|
||||||
|
html` <paper-tab data-entity=${platform}>
|
||||||
|
${this._getPlatformName(platform)}
|
||||||
|
</paper-tab>`
|
||||||
|
)}
|
||||||
|
</ha-tabs>
|
||||||
|
</div>`
|
||||||
|
: ""}
|
||||||
|
</ha-top-app-bar-fixed>
|
||||||
|
<div class="content">
|
||||||
|
<ha-card>
|
||||||
|
${!this._messages?.length
|
||||||
|
? html`<div class="card-content empty">
|
||||||
|
${this.hass.localize("ui.panel.mailbox.empty")}
|
||||||
|
</div>`
|
||||||
|
: nothing}
|
||||||
|
${this._messages?.map(
|
||||||
|
(message) =>
|
||||||
|
html` <paper-item
|
||||||
|
.message=${message}
|
||||||
|
@click=${this._openMP3Dialog}
|
||||||
|
>
|
||||||
|
<paper-item-body style="width:100%" two-line>
|
||||||
|
<div class="row">
|
||||||
|
<div>${message.caller}</div>
|
||||||
|
<div class="tip">
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.duration.second",
|
||||||
|
"count",
|
||||||
|
message.duration
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div secondary>
|
||||||
|
<span class="date">${message.timestamp}</span> -
|
||||||
|
${message.message}
|
||||||
|
</div>
|
||||||
|
</paper-item-body>
|
||||||
|
</paper-item>`
|
||||||
|
)}
|
||||||
|
</ha-card>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
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<MailboxMessage[]>("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<any[]> {
|
||||||
|
return this.hass.callApi<any[]>("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;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user