mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-22 00:36:34 +00:00
Migrate push notification toggle from Polymer to Lit (#18565)
This commit is contained in:
parent
3da7025d78
commit
1d2dc37f75
@ -1,10 +1,10 @@
|
||||
import { html } from "@polymer/polymer/lib/utils/html-tag";
|
||||
/* eslint-plugin-disable lit */
|
||||
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
||||
import { LitElement, TemplateResult, html } from "lit";
|
||||
import { customElement, property, state } from "lit/decorators";
|
||||
import { getAppKey } from "../data/notify_html5";
|
||||
import { showPromptDialog } from "../dialogs/generic/show-dialog-box";
|
||||
import { EventsMixin } from "../mixins/events-mixin";
|
||||
import "./ha-switch";
|
||||
import { HaSwitch } from "./ha-switch";
|
||||
import { HomeAssistant } from "../types";
|
||||
import { fireEvent } from "../common/dom/fire_event";
|
||||
|
||||
export const pushSupported =
|
||||
"serviceWorker" in navigator &&
|
||||
@ -13,39 +13,27 @@ export const pushSupported =
|
||||
document.location.hostname === "localhost" ||
|
||||
document.location.hostname === "127.0.0.1");
|
||||
|
||||
/*
|
||||
* @appliesMixin EventsMixin
|
||||
*/
|
||||
class HaPushNotificationsToggle extends EventsMixin(PolymerElement) {
|
||||
static get template() {
|
||||
@customElement("ha-push-notifications-toggle")
|
||||
class HaPushNotificationsToggle extends LitElement {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
||||
@state() private _disabled: boolean = false;
|
||||
|
||||
@state() private _pushChecked: boolean =
|
||||
"Notification" in window && Notification.permission === "granted";
|
||||
|
||||
@state() private _loading: boolean = true;
|
||||
|
||||
protected render(): TemplateResult {
|
||||
return html`
|
||||
<ha-switch
|
||||
disabled="[[_compDisabled(disabled, loading)]]"
|
||||
checked="{{pushChecked}}"
|
||||
on-change="handlePushChange"
|
||||
.disabled=${this._disabled || this._loading}
|
||||
.checked=${this._pushChecked}
|
||||
@change=${this._handlePushChange}
|
||||
></ha-switch>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
return {
|
||||
hass: { type: Object, value: null },
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
value: false,
|
||||
},
|
||||
pushChecked: {
|
||||
type: Boolean,
|
||||
value:
|
||||
"Notification" in window && Notification.permission === "granted",
|
||||
},
|
||||
loading: {
|
||||
type: Boolean,
|
||||
value: true,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
async connectedCallback() {
|
||||
super.connectedCallback();
|
||||
|
||||
@ -57,32 +45,33 @@ class HaPushNotificationsToggle extends EventsMixin(PolymerElement) {
|
||||
return;
|
||||
}
|
||||
reg.pushManager.getSubscription().then((subscription) => {
|
||||
this.loading = false;
|
||||
this.pushChecked = !!subscription;
|
||||
this._loading = false;
|
||||
this._pushChecked = !!subscription;
|
||||
});
|
||||
} catch (err) {
|
||||
// We don't set loading to `false` so we remain disabled
|
||||
}
|
||||
}
|
||||
|
||||
handlePushChange(event) {
|
||||
private _handlePushChange(ev: Event) {
|
||||
// Somehow this is triggered on Safari on page load causing
|
||||
// it to get into a loop and crash the page.
|
||||
if (!pushSupported) return;
|
||||
|
||||
if (event.target.checked) {
|
||||
this.subscribePushNotifications();
|
||||
const pushnotifications = (ev.target as HaSwitch).checked;
|
||||
if (pushnotifications) {
|
||||
this._subscribePushNotifications();
|
||||
} else {
|
||||
this.unsubscribePushNotifications();
|
||||
this._unsubscribePushNotifications();
|
||||
}
|
||||
}
|
||||
|
||||
async subscribePushNotifications() {
|
||||
private async _subscribePushNotifications() {
|
||||
const reg = await navigator.serviceWorker.ready;
|
||||
let sub;
|
||||
|
||||
try {
|
||||
let browserName;
|
||||
let browserName: string;
|
||||
if (navigator.userAgent.toLowerCase().indexOf("firefox") > -1) {
|
||||
browserName = "firefox";
|
||||
} else {
|
||||
@ -98,11 +87,11 @@ class HaPushNotificationsToggle extends EventsMixin(PolymerElement) {
|
||||
),
|
||||
});
|
||||
if (name == null) {
|
||||
this.pushChecked = false;
|
||||
this._pushChecked = false;
|
||||
return;
|
||||
}
|
||||
|
||||
let applicationServerKey;
|
||||
let applicationServerKey: Uint8Array | null;
|
||||
try {
|
||||
applicationServerKey = await getAppKey(this.hass);
|
||||
} catch (ex) {
|
||||
@ -123,7 +112,7 @@ class HaPushNotificationsToggle extends EventsMixin(PolymerElement) {
|
||||
browser: browserName,
|
||||
name,
|
||||
});
|
||||
} catch (err) {
|
||||
} catch (err: any) {
|
||||
const message = err.message || "Notification registration failed.";
|
||||
if (sub) {
|
||||
await sub.unsubscribe();
|
||||
@ -132,12 +121,12 @@ class HaPushNotificationsToggle extends EventsMixin(PolymerElement) {
|
||||
// eslint-disable-next-line
|
||||
console.error(err);
|
||||
|
||||
this.fire("hass-notification", { message });
|
||||
this.pushChecked = false;
|
||||
fireEvent(this, "hass-notification", { message });
|
||||
this._pushChecked = false;
|
||||
}
|
||||
}
|
||||
|
||||
async unsubscribePushNotifications() {
|
||||
private async _unsubscribePushNotifications() {
|
||||
const reg = await navigator.serviceWorker.ready;
|
||||
|
||||
try {
|
||||
@ -147,24 +136,21 @@ class HaPushNotificationsToggle extends EventsMixin(PolymerElement) {
|
||||
|
||||
await this.hass.callApi("DELETE", "notify.html5", { subscription: sub });
|
||||
await sub.unsubscribe();
|
||||
} catch (err) {
|
||||
} catch (err: any) {
|
||||
const message =
|
||||
err.message || "Failed unsubscribing for push notifications.";
|
||||
|
||||
// eslint-disable-next-line
|
||||
console.error("Error in unsub push", err);
|
||||
|
||||
this.fire("hass-notification", { message });
|
||||
this.pushChecked = true;
|
||||
fireEvent(this, "hass-notification", { message });
|
||||
this._pushChecked = true;
|
||||
}
|
||||
}
|
||||
|
||||
_compDisabled(disabled, loading) {
|
||||
return disabled || loading;
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define(
|
||||
"ha-push-notifications-toggle",
|
||||
HaPushNotificationsToggle
|
||||
);
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"ha-push-notifications-toggle": HaPushNotificationsToggle;
|
||||
}
|
||||
}
|
@ -1,91 +0,0 @@
|
||||
import "@polymer/iron-flex-layout/iron-flex-layout-classes";
|
||||
import { html } from "@polymer/polymer/lib/utils/html-tag";
|
||||
/* eslint-plugin-disable lit */
|
||||
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
||||
import { isComponentLoaded } from "../../common/config/is_component_loaded";
|
||||
import { pushSupported } from "../../components/ha-push-notifications-toggle";
|
||||
import "../../components/ha-settings-row";
|
||||
import LocalizeMixin from "../../mixins/localize-mixin";
|
||||
import { documentationUrl } from "../../util/documentation-url";
|
||||
|
||||
/*
|
||||
* @appliesMixin LocalizeMixin
|
||||
*/
|
||||
class HaPushNotificationsRow extends LocalizeMixin(PolymerElement) {
|
||||
static get template() {
|
||||
return html`
|
||||
<style>
|
||||
a {
|
||||
color: var(--primary-color);
|
||||
}
|
||||
</style>
|
||||
<ha-settings-row narrow="[[narrow]]">
|
||||
<span slot="heading"
|
||||
>[[localize('ui.panel.profile.push_notifications.header')]]</span
|
||||
>
|
||||
<span slot="description">
|
||||
[[localize(_descrLocalizeKey)]]
|
||||
<a
|
||||
href="[[_computeDocumentationUrl(hass)]]"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>[[localize('ui.panel.profile.push_notifications.link_promo')]]</a
|
||||
>
|
||||
</span>
|
||||
<ha-push-notifications-toggle
|
||||
hass="[[hass]]"
|
||||
disabled="[[_error]]"
|
||||
></ha-push-notifications-toggle>
|
||||
</ha-settings-row>
|
||||
`;
|
||||
}
|
||||
|
||||
static get properties() {
|
||||
return {
|
||||
hass: Object,
|
||||
narrow: Boolean,
|
||||
_descrLocalizeKey: {
|
||||
type: String,
|
||||
computed: "_descriptionKey(_platformLoaded, _pushSupported)",
|
||||
},
|
||||
_platformLoaded: {
|
||||
type: Boolean,
|
||||
computed: "_compPlatformLoaded(hass)",
|
||||
},
|
||||
_pushSupported: {
|
||||
type: Boolean,
|
||||
value: pushSupported,
|
||||
},
|
||||
_error: {
|
||||
type: Boolean,
|
||||
computed: "_compError(_platformLoaded, _pushSupported)",
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
_computeDocumentationUrl(hass) {
|
||||
return documentationUrl(hass, "/integrations/html5");
|
||||
}
|
||||
|
||||
_compPlatformLoaded(hass) {
|
||||
return isComponentLoaded(hass, "notify.html5");
|
||||
}
|
||||
|
||||
_compError(platformLoaded, pushSupported_) {
|
||||
return !platformLoaded || !pushSupported_;
|
||||
}
|
||||
|
||||
_descriptionKey(platformLoaded, pushSupported_) {
|
||||
let key;
|
||||
if (!pushSupported_) {
|
||||
key = "error_use_https";
|
||||
} else if (!platformLoaded) {
|
||||
key = "error_load_platform";
|
||||
} else {
|
||||
key = "description";
|
||||
}
|
||||
return `ui.panel.profile.push_notifications.${key}`;
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define("ha-push-notifications-row", HaPushNotificationsRow);
|
72
src/panels/profile/ha-push-notifications-row.ts
Normal file
72
src/panels/profile/ha-push-notifications-row.ts
Normal file
@ -0,0 +1,72 @@
|
||||
import { LitElement, TemplateResult, css, html } from "lit";
|
||||
import { customElement, property } from "lit/decorators";
|
||||
import { isComponentLoaded } from "../../common/config/is_component_loaded";
|
||||
import { pushSupported } from "../../components/ha-push-notifications-toggle";
|
||||
import "../../components/ha-settings-row";
|
||||
import { documentationUrl } from "../../util/documentation-url";
|
||||
import { HomeAssistant } from "../../types";
|
||||
|
||||
@customElement("ha-push-notifications-row")
|
||||
class HaPushNotificationsRow extends LitElement {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
||||
@property() public narrow!: boolean;
|
||||
|
||||
protected render(): TemplateResult {
|
||||
const platformLoaded = isComponentLoaded(this.hass, "notify.html5");
|
||||
let descriptionKey:
|
||||
| "error_use_https"
|
||||
| "error_load_platform"
|
||||
| "description";
|
||||
if (!pushSupported) {
|
||||
descriptionKey = "error_use_https";
|
||||
} else if (!platformLoaded) {
|
||||
descriptionKey = "error_load_platform";
|
||||
} else {
|
||||
descriptionKey = "description";
|
||||
}
|
||||
|
||||
const isDisabled = !platformLoaded || !pushSupported;
|
||||
|
||||
return html`
|
||||
<ha-settings-row .narrow=${this.narrow}>
|
||||
<span slot="heading"
|
||||
>${this.hass.localize(
|
||||
"ui.panel.profile.push_notifications.header"
|
||||
)}</span
|
||||
>
|
||||
<span slot="description">
|
||||
${this.hass.localize(
|
||||
`ui.panel.profile.push_notifications.${descriptionKey}`
|
||||
)}
|
||||
<a
|
||||
href=${documentationUrl(this.hass, "/integrations/html5")}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>${this.hass.localize(
|
||||
"ui.panel.profile.push_notifications.link_promo"
|
||||
)}</a
|
||||
>
|
||||
</span>
|
||||
<ha-push-notifications-toggle
|
||||
.hass=${this.hass}
|
||||
.disabled=${isDisabled}
|
||||
></ha-push-notifications-toggle>
|
||||
</ha-settings-row>
|
||||
`;
|
||||
}
|
||||
|
||||
static get styles() {
|
||||
return css`
|
||||
a {
|
||||
color: var(--primary-color);
|
||||
}
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"ha-push-notifications-row": HaPushNotificationsRow;
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user