diff --git a/ts/WoltLabSuite/Core/Notification/Handler.ts b/ts/WoltLabSuite/Core/Notification/Handler.ts index 1da2b00f454..a156989accb 100644 --- a/ts/WoltLabSuite/Core/Notification/Handler.ts +++ b/ts/WoltLabSuite/Core/Notification/Handler.ts @@ -12,7 +12,7 @@ import * as Ajax from "../Ajax"; import { AjaxCallbackSetup } from "../Ajax/Data"; import * as Core from "../Core"; import * as EventHandler from "../Event/Handler"; -import { serviceWorkerSupported } from "./ServiceWorker"; +import { serviceWorkerSupported, updateNotificationLastReadTime } from "./ServiceWorker"; import { updateCounter } from "WoltLabSuite/Core/Ui/User/Menu/Manager"; interface NotificationHandlerOptions { @@ -206,6 +206,9 @@ class NotificationHandler { this.lastRequestTimestamp = data.returnValues.lastRequestTimestamp; + // Update the last read time for the service worker + updateNotificationLastReadTime(this.lastRequestTimestamp); + EventHandler.fire("com.woltlab.wcf.notification", "afterPoll", pollData); this.showNotification(pollData); @@ -264,6 +267,10 @@ class NotificationHandler { silent: !window.ENABLE_DEBUG_MODE, }; } + + updateLastRequestTimestamp(timestamp: number): void { + this.lastRequestTimestamp = Math.max(timestamp, this.lastRequestTimestamp); + } } let notificationHandler: NotificationHandler; @@ -281,6 +288,10 @@ export function enableNotifications(): void { notificationHandler!.enableNotifications(); } +export function updateLastRequestTimestamp(timestamp: number): void { + notificationHandler?.updateLastRequestTimestamp(timestamp); +} + export function poll(): void { notificationHandler?.dispatchRequest(); } diff --git a/ts/WoltLabSuite/Core/Notification/ServiceWorker.ts b/ts/WoltLabSuite/Core/Notification/ServiceWorker.ts index d24b8136c3f..cff50ae9fb1 100644 --- a/ts/WoltLabSuite/Core/Notification/ServiceWorker.ts +++ b/ts/WoltLabSuite/Core/Notification/ServiceWorker.ts @@ -7,6 +7,7 @@ */ import { prepareRequest } from "WoltLabSuite/Core/Ajax/Backend"; +import { updateLastRequestTimestamp } from "WoltLabSuite/Core/Notification/Handler"; let _serviceWorker: ServiceWorker | null = null; @@ -24,6 +25,15 @@ class ServiceWorker { scope: "/", }); this.#serviceWorkerRegistration = window.navigator.serviceWorker.ready; + + window.navigator.serviceWorker.addEventListener("message", (event) => { + // Validate that this is a message from our service worker + if (!(event.source instanceof window.ServiceWorker) || event.source.scriptURL !== this.#serviceWorkerJsUrl) { + return; + } + + updateLastRequestTimestamp(event.data.time); + }); } async register(): Promise { diff --git a/wcfsetup/install/files/js/WoltLabSuite/Core/Notification/Handler.js b/wcfsetup/install/files/js/WoltLabSuite/Core/Notification/Handler.js index 35691130f76..94d2b9473ee 100644 --- a/wcfsetup/install/files/js/WoltLabSuite/Core/Notification/Handler.js +++ b/wcfsetup/install/files/js/WoltLabSuite/Core/Notification/Handler.js @@ -12,6 +12,7 @@ define(["require", "exports", "tslib", "../Ajax", "../Core", "../Event/Handler", Object.defineProperty(exports, "__esModule", { value: true }); exports.setup = setup; exports.enableNotifications = enableNotifications; + exports.updateLastRequestTimestamp = updateLastRequestTimestamp; exports.poll = poll; Ajax = tslib_1.__importStar(Ajax); Core = tslib_1.__importStar(Core); @@ -155,6 +156,8 @@ define(["require", "exports", "tslib", "../Ajax", "../Core", "../Event/Handler", this.prepareNextRequest(); } this.lastRequestTimestamp = data.returnValues.lastRequestTimestamp; + // Update the last read time for the service worker + (0, ServiceWorker_1.updateNotificationLastReadTime)(this.lastRequestTimestamp); EventHandler.fire("com.woltlab.wcf.notification", "afterPoll", pollData); this.showNotification(pollData); } @@ -205,6 +208,9 @@ define(["require", "exports", "tslib", "../Ajax", "../Core", "../Event/Handler", silent: !window.ENABLE_DEBUG_MODE, }; } + updateLastRequestTimestamp(timestamp) { + this.lastRequestTimestamp = Math.max(timestamp, this.lastRequestTimestamp); + } } let notificationHandler; /** @@ -218,6 +224,9 @@ define(["require", "exports", "tslib", "../Ajax", "../Core", "../Event/Handler", function enableNotifications() { notificationHandler.enableNotifications(); } + function updateLastRequestTimestamp(timestamp) { + notificationHandler?.updateLastRequestTimestamp(timestamp); + } function poll() { notificationHandler?.dispatchRequest(); } diff --git a/wcfsetup/install/files/js/WoltLabSuite/Core/Notification/ServiceWorker.js b/wcfsetup/install/files/js/WoltLabSuite/Core/Notification/ServiceWorker.js index 80f54f4ea4c..49e07ea7b5a 100644 --- a/wcfsetup/install/files/js/WoltLabSuite/Core/Notification/ServiceWorker.js +++ b/wcfsetup/install/files/js/WoltLabSuite/Core/Notification/ServiceWorker.js @@ -5,7 +5,7 @@ * @since 6.1 * @woltlabExcludeBundle tiny */ -define(["require", "exports", "WoltLabSuite/Core/Ajax/Backend"], function (require, exports, Backend_1) { +define(["require", "exports", "WoltLabSuite/Core/Ajax/Backend", "WoltLabSuite/Core/Notification/Handler"], function (require, exports, Backend_1, Handler_1) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.serviceWorkerSupported = serviceWorkerSupported; @@ -26,6 +26,13 @@ define(["require", "exports", "WoltLabSuite/Core/Ajax/Backend"], function (requi scope: "/", }); this.#serviceWorkerRegistration = window.navigator.serviceWorker.ready; + window.navigator.serviceWorker.addEventListener("message", (event) => { + // Validate that this is a message from our service worker + if (!(event.source instanceof window.ServiceWorker) || event.source.scriptURL !== this.#serviceWorkerJsUrl) { + return; + } + (0, Handler_1.updateLastRequestTimestamp)(event.data.time); + }); } async register() { const currentSubscription = await (await this.#serviceWorkerRegistration).pushManager.getSubscription();