* 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.
120 lines
3.8 KiB
JavaScript
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();
|
|
});
|
|
}
|