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/app/lib/push-notifications.js
2020-12-18 09:03:51 -06:00

172 lines
4.3 KiB
JavaScript

import KeyValueStore from "discourse/lib/key-value-store";
import { ajax } from "discourse/lib/ajax";
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], 10) < 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 &&
!user.isInDoNotDisturb() &&
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) => {
// eslint-disable-next-line no-console
console.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) => {
// eslint-disable-next-line no-console
console.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) => {
// eslint-disable-next-line no-console
console.error(e);
});
if (callback) {
callback();
}
});
}