This repository has been archived on 2023-03-18. You can view files and clone it, but cannot push or open issues or pull requests.
osr-discourse-src/app/assets/javascripts/discourse/lib/push-notifications.js.es6
Jeff Wong 91b31860a1
Feature: Push notifications for Android (#5792)
* Feature: Push notifications for Android

Notification config for desktop and mobile are merged.

Desktop notifications stay as they are for desktop views.

If mobile mode, push notifications are enabled.

Added push notification subscriptions in their own table, rather than through
custom fields.

Notification banner prompts appear for both mobile and desktop when enabled.
2018-05-04 15:31:48 -07:00

120 lines
3.8 KiB
JavaScript

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();
});
}