Rename things, add comments
This commit is contained in:
		
							parent
							
								
									1abcc88fce
								
							
						
					
					
						commit
						9d5556c7f5
					
				
					 4 changed files with 30 additions and 24 deletions
				
			
		|  | @ -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) { | ||||||
|  |  | ||||||
|  | @ -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(); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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(); | ||||||
|  | @ -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"); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue