126 lines
4.2 KiB
TypeScript
126 lines
4.2 KiB
TypeScript
import { callApi } from '../api/gramjs';
|
|
import { DEBUG } from '../config';
|
|
import { getDispatch, getGlobal } from '../lib/teact/teactn';
|
|
import { IS_SERVICE_WORKER_SUPPORTED } from './environment';
|
|
|
|
function getDeviceToken(subscription: PushSubscription) {
|
|
const data = subscription.toJSON();
|
|
return JSON.stringify({ endpoint: data.endpoint, keys: data.keys });
|
|
}
|
|
|
|
function checkIfSupported() {
|
|
if (!IS_SERVICE_WORKER_SUPPORTED) return false;
|
|
if (!('showNotification' in ServiceWorkerRegistration.prototype)) {
|
|
if (DEBUG) {
|
|
// eslint-disable-next-line no-console
|
|
console.log('[PUSH] Push notifications aren\'t supported.');
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// Check the current Notification permission.
|
|
// If its denied, it's a permanent block until the
|
|
// user changes the permission
|
|
if (Notification.permission === 'denied') {
|
|
if (DEBUG) {
|
|
// eslint-disable-next-line no-console
|
|
console.log('[PUSH] The user has blocked push notifications.');
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// Check if push messaging is supported
|
|
if (!('PushManager' in window)) {
|
|
if (DEBUG) {
|
|
// eslint-disable-next-line no-console
|
|
console.log('[PUSH] Push messaging isn\'t supported.');
|
|
}
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
const expirationTime = 12 * 60 * 60 * 1000; // 12 hours
|
|
|
|
function checkIfShouldResubscribe(subscription: PushSubscription | null) {
|
|
const global = getGlobal();
|
|
if (!global.push || !subscription) return true;
|
|
if (getDeviceToken(subscription) !== global.push.deviceToken) return true;
|
|
return Date.now() - global.push.subscribedAt > expirationTime;
|
|
}
|
|
|
|
async function unsubscribe(subscription: PushSubscription | null) {
|
|
const global = getGlobal();
|
|
const dispatch = getDispatch();
|
|
if (subscription) {
|
|
try {
|
|
const deviceToken = getDeviceToken(subscription);
|
|
await callApi('unregisterDevice', deviceToken);
|
|
await subscription.unsubscribe();
|
|
dispatch.deleteDeviceToken();
|
|
return;
|
|
} catch (error) {
|
|
if (DEBUG) {
|
|
// eslint-disable-next-line no-console
|
|
console.log('[PUSH] Unable to unsubscribe from push.', error);
|
|
}
|
|
}
|
|
}
|
|
if (global.push) {
|
|
await callApi('unregisterDevice', global.push.deviceToken);
|
|
dispatch.deleteDeviceToken();
|
|
}
|
|
}
|
|
|
|
export async function unsubscribeFromPush() {
|
|
if (!checkIfSupported()) return;
|
|
const serviceWorkerRegistration = await navigator.serviceWorker.ready;
|
|
const subscription = await serviceWorkerRegistration.pushManager.getSubscription();
|
|
await unsubscribe(subscription);
|
|
}
|
|
|
|
export async function subscribeToPush() {
|
|
if (!checkIfSupported()) return;
|
|
const serviceWorkerRegistration = await navigator.serviceWorker.ready;
|
|
let subscription = await serviceWorkerRegistration.pushManager.getSubscription();
|
|
if (!checkIfShouldResubscribe(subscription)) return;
|
|
await unsubscribe(subscription);
|
|
try {
|
|
subscription = await serviceWorkerRegistration.pushManager.subscribe({
|
|
userVisibleOnly: true,
|
|
});
|
|
const deviceToken = getDeviceToken(subscription);
|
|
if (DEBUG) {
|
|
// eslint-disable-next-line no-console
|
|
console.log('[PUSH] Received push subscription: ', deviceToken);
|
|
}
|
|
await callApi('registerDevice', deviceToken);
|
|
getDispatch().setDeviceToken(deviceToken);
|
|
} catch (error) {
|
|
if (Notification.permission === 'denied' as NotificationPermission) {
|
|
// The user denied the notification permission which
|
|
// means we failed to subscribe and the user will need
|
|
// to manually change the notification permission to
|
|
// subscribe to push messages
|
|
if (DEBUG) {
|
|
// eslint-disable-next-line no-console
|
|
console.log('[PUSH] Permission for Notifications was denied');
|
|
}
|
|
} else if (DEBUG) {
|
|
// A problem occurred with the subscription, this can
|
|
// often be down to an issue or lack of the gcm_sender_id
|
|
// and / or gcm_user_visible_only
|
|
// eslint-disable-next-line no-console
|
|
console.log('[PUSH] Unable to subscribe to push.', error);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Notify service worker that client is fully loaded
|
|
export function notifyClientReady() {
|
|
if (!navigator.serviceWorker.controller) return;
|
|
navigator.serviceWorker.controller.postMessage({
|
|
type: 'clientReady',
|
|
});
|
|
}
|