import { ajax } from 'discourse/lib/ajax'; import KeyValueStore from 'discourse/lib/key-value-store'; export const keyValueStore = new KeyValueStore("discourse_push_notifications_"); export function userSubscriptionKey(user) { return `subscribed-${user.get('id')}`; } function sendSubscriptionToServer(subscription, sendConfirmation) { ajax('/push_notifications/subscribe', { type: 'POST', data: { subscription: subscription.toJSON(), send_confirmation: sendConfirmation } }); } function userAgentVersionChecker(agent, version, mobileView) { const uaMatch = navigator.userAgent.match(new RegExp(`${agent}\/(\\d+)\\.\\d`)); if (uaMatch && mobileView) return false; if (!uaMatch || parseInt(uaMatch[1]) < version) return false; return true; } function resetIdle() { if('controller' in navigator.serviceWorker && navigator.serviceWorker.controller != null) { navigator.serviceWorker.controller.postMessage({lastAction: Date.now()}); } } function setupActivityListeners(appEvents) { window.addEventListener("focus", resetIdle); if (document) { document.addEventListener("scroll", resetIdle); } appEvents.on('page:changed', resetIdle); } export function isPushNotificationsSupported(mobileView) { if (!(('serviceWorker' in navigator) && (ServiceWorkerRegistration && (typeof(Notification) !== "undefined") && ('showNotification' in ServiceWorkerRegistration.prototype) && ('PushManager' in window)))) { return false; } if ((!userAgentVersionChecker('Firefox', 44, mobileView)) && (!userAgentVersionChecker('Chrome', 50))) { return false; } return true; } export function isPushNotificationsEnabled(user, mobileView) { return user && isPushNotificationsSupported(mobileView) && keyValueStore.getItem(userSubscriptionKey(user)); } export function register(user, mobileView, router, appEvents) { if (!isPushNotificationsSupported(mobileView)) return; if (Notification.permission === 'denied' || !user) return; navigator.serviceWorker.ready.then(serviceWorkerRegistration => { serviceWorkerRegistration.pushManager.getSubscription().then(subscription => { if (subscription) { sendSubscriptionToServer(subscription, false); // Resync localStorage keyValueStore.setItem(userSubscriptionKey(user), 'subscribed'); } setupActivityListeners(appEvents); }).catch(e => Ember.Logger.error(e)); }); navigator.serviceWorker.addEventListener('message', (event) => { if ('url' in event.data) { const url = event.data.url; router.handleURL(url); } }); } export function subscribe(callback, applicationServerKey, mobileView) { if (!isPushNotificationsSupported(mobileView)) return; navigator.serviceWorker.ready.then(serviceWorkerRegistration => { serviceWorkerRegistration.pushManager.subscribe({ userVisibleOnly: true, applicationServerKey: new Uint8Array(applicationServerKey.split("|")) // eslint-disable-line no-undef }).then(subscription => { sendSubscriptionToServer(subscription, true); if (callback) callback(); }).catch(e => Ember.Logger.error(e)); }); } export function unsubscribe(user, callback, mobileView) { if (!isPushNotificationsSupported(mobileView)) return; keyValueStore.setItem(userSubscriptionKey(user), ''); navigator.serviceWorker.ready.then(serviceWorkerRegistration => { serviceWorkerRegistration.pushManager.getSubscription().then(subscription => { if (subscription) { subscription.unsubscribe().then((successful) => { if (successful) { ajax('/push_notifications/unsubscribe', { type: 'POST', data: { subscription: subscription.toJSON() } }); } }); } }).catch(e => Ember.Logger.error(e)); if (callback) callback(); }); }