Rename things, add comments

pull/751/head
binwiederhier 2023-06-10 20:42:02 -04:00
parent 1abcc88fce
commit 9d5556c7f5
4 changed files with 30 additions and 24 deletions

View File

@ -33,8 +33,8 @@ class Prefs {
} }
async webPushEnabled() { async webPushEnabled() {
const obj = await this.db.prefs.get("webPushEnabled"); const webPushEnabled = await this.db.prefs.get("webPushEnabled");
return obj?.value ?? false; return webPushEnabled?.value ?? false;
} }
async setWebPushEnabled(enabled) { async setWebPushEnabled(enabled) {

View File

@ -20,16 +20,15 @@ class SubscriptionManager {
); );
} }
/** List of topics for which Web Push is enabled, excludes internal topics; returns empty list if Web Push is disabled */
async webPushTopics() { async webPushTopics() {
// the Promise.resolve wrapper is not superfluous, without it the live query breaks: // the Promise.resolve wrapper is not superfluous, without it the live query breaks:
// https://dexie.org/docs/dexie-react-hooks/useLiveQuery()#calling-non-dexie-apis-from-querier // https://dexie.org/docs/dexie-react-hooks/useLiveQuery()#calling-non-dexie-apis-from-querier
if (!(await Promise.resolve(notifier.pushEnabled()))) { const pushEnabled = await Promise.resolve(notifier.pushEnabled());
if (!pushEnabled) {
return []; return [];
} }
const subscriptions = await this.db.subscriptions.where({ mutedUntil: 0, baseUrl: config.base_url }).toArray(); const subscriptions = await this.db.subscriptions.where({ mutedUntil: 0, baseUrl: config.base_url }).toArray();
// internal is currently a bool, it could be a 0/1 to be indexable, but for now just filter them out here
return subscriptions.filter(({ internal }) => !internal).map(({ topic }) => topic); return subscriptions.filter(({ internal }) => !internal).map(({ topic }) => topic);
} }
@ -111,7 +110,7 @@ class SubscriptionManager {
); );
} }
async refreshWebPushSubscriptions(presetTopics) { async updateWebPushSubscriptions(presetTopics) {
const topics = presetTopics ?? (await this.webPushTopics()); const topics = presetTopics ?? (await this.webPushTopics());
const browserSubscription = await notifier.getBrowserSubscription(); const browserSubscription = await notifier.getBrowserSubscription();

View File

@ -3,21 +3,26 @@ import { useLiveQuery } from "dexie-react-hooks";
import notifier from "./Notifier"; import notifier from "./Notifier";
import subscriptionManager from "./SubscriptionManager"; import subscriptionManager from "./SubscriptionManager";
export const useWebPushUpdateWorker = () => { const intervalMillis = 13 * 60 * 1_000; // 13 minutes
const updateIntervalMillis = 60 * 60 * 1_000; // 1 hour
/**
* Updates the Web Push subscriptions when the list of topics changes.
*/
export const useWebPushTopicListener = () => {
const topics = useLiveQuery(() => subscriptionManager.webPushTopics()); const topics = useLiveQuery(() => subscriptionManager.webPushTopics());
const [lastTopics, setLastTopics] = useState(); const [lastTopics, setLastTopics] = useState();
useEffect(() => { useEffect(() => {
if (!notifier.pushPossible() || JSON.stringify(topics) === JSON.stringify(lastTopics)) { const topicsChanged = JSON.stringify(topics) !== JSON.stringify(lastTopics);
if (!notifier.pushPossible() || !topicsChanged) {
return; return;
} }
(async () => { (async () => {
try { try {
console.log("[useWebPushUpdateWorker] Refreshing web push subscriptions"); console.log("[useWebPushUpdateWorker] Refreshing web push subscriptions");
await subscriptionManager.updateWebPushSubscriptions(topics);
await subscriptionManager.refreshWebPushSubscriptions(topics);
setLastTopics(topics); setLastTopics(topics);
} catch (e) { } catch (e) {
console.error("[useWebPushUpdateWorker] Error refreshing web push subscriptions", e); console.error("[useWebPushUpdateWorker] Error refreshing web push subscriptions", e);
@ -26,10 +31,13 @@ export const useWebPushUpdateWorker = () => {
}, [topics, lastTopics]); }, [topics, lastTopics]);
}; };
const intervalMillis = 13 * 60 * 1_000; // 13 minutes /**
const updateIntervalMillis = 60 * 60 * 1_000; // 1 hour * Helper class for Web Push that does three things:
* 1. Updates the Web Push subscriptions on a schedule
class WebPushRefreshWorker { * 2. Updates the Web Push subscriptions when the window is minimised / app switched
* 3. Listens to the broadcast channel from the service worker to play a sound when a message comes in
*/
class WebPushWorker {
constructor() { constructor() {
this.timer = null; this.timer = null;
this.lastUpdate = null; this.lastUpdate = null;
@ -43,7 +51,6 @@ class WebPushRefreshWorker {
} }
this.timer = setInterval(() => this.updateSubscriptions(), intervalMillis); this.timer = setInterval(() => this.updateSubscriptions(), intervalMillis);
this.broadcastChannel = new BroadcastChannel("web-push-broadcast"); this.broadcastChannel = new BroadcastChannel("web-push-broadcast");
this.broadcastChannel.addEventListener("message", this.messageHandler); this.broadcastChannel.addEventListener("message", this.messageHandler);
@ -60,7 +67,7 @@ class WebPushRefreshWorker {
} }
onMessage() { onMessage() {
notifier.playSound(); notifier.playSound(); // Service Worker cannot play sound, so we do it here!
} }
onVisibilityChange() { onVisibilityChange() {
@ -75,10 +82,10 @@ class WebPushRefreshWorker {
} }
if (!this.lastUpdate || Date.now() - this.lastUpdate > updateIntervalMillis) { if (!this.lastUpdate || Date.now() - this.lastUpdate > updateIntervalMillis) {
await subscriptionManager.refreshWebPushSubscriptions(); await subscriptionManager.updateWebPushSubscriptions();
this.lastUpdate = Date.now(); this.lastUpdate = Date.now();
} }
} }
} }
export const webPushRefreshWorker = new WebPushRefreshWorker(); export const webPush = new WebPushWorker();

View File

@ -9,7 +9,7 @@ import pruner from "../app/Pruner";
import session from "../app/Session"; import session from "../app/Session";
import accountApi from "../app/AccountApi"; import accountApi from "../app/AccountApi";
import { UnauthorizedError } from "../app/errors"; import { UnauthorizedError } from "../app/errors";
import { webPushRefreshWorker, useWebPushUpdateWorker } from "../app/WebPushWorker"; import { webPush, useWebPushTopicListener } from "../app/WebPush";
/** /**
* Wire connectionManager and subscriptionManager so that subscriptions are updated when the connection * Wire connectionManager and subscriptionManager so that subscriptions are updated when the connection
@ -134,18 +134,18 @@ const stopWorkers = () => {
poller.stopWorker(); poller.stopWorker();
pruner.stopWorker(); pruner.stopWorker();
accountApi.stopWorker(); accountApi.stopWorker();
webPushRefreshWorker.stopWorker(); webPush.stopWorker();
}; };
const startWorkers = () => { const startWorkers = () => {
poller.startWorker(); poller.startWorker();
pruner.startWorker(); pruner.startWorker();
accountApi.startWorker(); accountApi.startWorker();
webPushRefreshWorker.startWorker(); webPush.startWorker();
}; };
export const useBackgroundProcesses = () => { export const useBackgroundProcesses = () => {
useWebPushUpdateWorker(); useWebPushTopicListener();
useEffect(() => { useEffect(() => {
console.log("[useBackgroundProcesses] mounting"); console.log("[useBackgroundProcesses] mounting");