mirror of
https://github.com/home-assistant/frontend
synced 2024-09-25 09:39:00 +02:00
d5de435f06
* Fix html5 notification toggle * Update src/components/ha-push-notifications-toggle.ts Co-authored-by: Bram Kragten <mail@bramkragten.nl> * fix lint --------- Co-authored-by: alexyao2015 <alexyao2015@users.noreply.github.com> Co-authored-by: Bram Kragten <mail@bramkragten.nl>
157 lines
4.3 KiB
TypeScript
157 lines
4.3 KiB
TypeScript
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 { HaSwitch } from "./ha-switch";
|
|
import { HomeAssistant } from "../types";
|
|
import { fireEvent } from "../common/dom/fire_event";
|
|
|
|
export const pushSupported =
|
|
"serviceWorker" in navigator &&
|
|
"PushManager" in window &&
|
|
(document.location.protocol === "https:" ||
|
|
document.location.hostname === "localhost" ||
|
|
document.location.hostname === "127.0.0.1");
|
|
|
|
@customElement("ha-push-notifications-toggle")
|
|
class HaPushNotificationsToggle extends LitElement {
|
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
|
|
|
@property({ type: Boolean }) public disabled!: boolean;
|
|
|
|
@state() private _pushChecked: boolean =
|
|
"Notification" in window && Notification.permission === "granted";
|
|
|
|
@state() private _loading: boolean = true;
|
|
|
|
protected render(): TemplateResult {
|
|
return html`
|
|
<ha-switch
|
|
.disabled=${this.disabled || this._loading}
|
|
.checked=${this._pushChecked}
|
|
@change=${this._handlePushChange}
|
|
></ha-switch>
|
|
`;
|
|
}
|
|
|
|
async connectedCallback() {
|
|
super.connectedCallback();
|
|
|
|
if (!pushSupported) return;
|
|
|
|
try {
|
|
const reg = await navigator.serviceWorker.ready;
|
|
if (!reg.pushManager) {
|
|
return;
|
|
}
|
|
reg.pushManager.getSubscription().then((subscription) => {
|
|
this._loading = false;
|
|
this._pushChecked = !!subscription;
|
|
});
|
|
} catch (err) {
|
|
// We don't set loading to `false` so we remain disabled
|
|
}
|
|
}
|
|
|
|
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;
|
|
|
|
const pushnotifications = (ev.target as HaSwitch).checked;
|
|
if (pushnotifications) {
|
|
this._subscribePushNotifications();
|
|
} else {
|
|
this._unsubscribePushNotifications();
|
|
}
|
|
}
|
|
|
|
private async _subscribePushNotifications() {
|
|
const reg = await navigator.serviceWorker.ready;
|
|
let sub;
|
|
|
|
try {
|
|
let browserName: string;
|
|
if (navigator.userAgent.toLowerCase().indexOf("firefox") > -1) {
|
|
browserName = "firefox";
|
|
} else {
|
|
browserName = "chrome";
|
|
}
|
|
|
|
const name = await showPromptDialog(this, {
|
|
title: this.hass.localize(
|
|
"ui.panel.profile.push_notifications.add_device_prompt.title"
|
|
),
|
|
inputLabel: this.hass.localize(
|
|
"ui.panel.profile.push_notifications.add_device_prompt.input_label"
|
|
),
|
|
});
|
|
if (name == null) {
|
|
this._pushChecked = false;
|
|
return;
|
|
}
|
|
|
|
let applicationServerKey: Uint8Array | null;
|
|
try {
|
|
applicationServerKey = await getAppKey(this.hass);
|
|
} catch (ex) {
|
|
applicationServerKey = null;
|
|
}
|
|
|
|
if (applicationServerKey) {
|
|
sub = await reg.pushManager.subscribe({
|
|
userVisibleOnly: true,
|
|
applicationServerKey,
|
|
});
|
|
} else {
|
|
sub = await reg.pushManager.subscribe({ userVisibleOnly: true });
|
|
}
|
|
|
|
await this.hass.callApi("POST", "notify.html5", {
|
|
subscription: sub,
|
|
browser: browserName,
|
|
name,
|
|
});
|
|
} catch (err: any) {
|
|
const message = err.message || "Notification registration failed.";
|
|
if (sub) {
|
|
await sub.unsubscribe();
|
|
}
|
|
|
|
// eslint-disable-next-line
|
|
console.error(err);
|
|
|
|
fireEvent(this, "hass-notification", { message });
|
|
this._pushChecked = false;
|
|
}
|
|
}
|
|
|
|
private async _unsubscribePushNotifications() {
|
|
const reg = await navigator.serviceWorker.ready;
|
|
|
|
try {
|
|
const sub = await reg.pushManager.getSubscription();
|
|
|
|
if (!sub) return;
|
|
|
|
await this.hass.callApi("DELETE", "notify.html5", { subscription: sub });
|
|
await sub.unsubscribe();
|
|
} catch (err: any) {
|
|
const message =
|
|
err.message || "Failed unsubscribing for push notifications.";
|
|
|
|
// eslint-disable-next-line
|
|
console.error("Error in unsub push", err);
|
|
|
|
fireEvent(this, "hass-notification", { message });
|
|
this._pushChecked = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
declare global {
|
|
interface HTMLElementTagNameMap {
|
|
"ha-push-notifications-toggle": HaPushNotificationsToggle;
|
|
}
|
|
}
|