From ccb380852f344f74e7a8a72fddb20c0af6bb160a Mon Sep 17 00:00:00 2001 From: undefined Date: Wed, 31 Aug 2022 12:38:38 +0800 Subject: [PATCH] ui: add a useless service worker --- packages/ui-default/build/config/webpack.ts | 4 ++-- .../ui-default/components/message/index.page.ts | 6 ++++++ packages/ui-default/components/message/worker.ts | 13 +++++++++---- packages/ui-default/entry.js | 10 ++++++++++ packages/ui-default/package.json | 3 ++- packages/ui-default/service-worker.ts | 14 ++++++++++++++ 6 files changed, 43 insertions(+), 7 deletions(-) create mode 100644 packages/ui-default/service-worker.ts diff --git a/packages/ui-default/build/config/webpack.ts b/packages/ui-default/build/config/webpack.ts index 5078069da..dd4bdc67c 100644 --- a/packages/ui-default/build/config/webpack.ts +++ b/packages/ui-default/build/config/webpack.ts @@ -146,13 +146,13 @@ export default function (env: { production?: boolean, measure?: boolean } = {}) }, { test: /\.[mc]?[jt]sx?$/, - exclude: [/@types\//, /components\/message\//], + exclude: [/@types\//, /components\/message\//, /entry\.js/], type: 'javascript/auto', use: [esbuildLoader()], }, { test: /\.[mc]?[jt]sx?$/, - include: /components\/message\//, + include: [/components\/message\//, /entry\.js/], type: 'javascript/auto', use: [{ loader: 'ts-loader', diff --git a/packages/ui-default/components/message/index.page.ts b/packages/ui-default/components/message/index.page.ts index c18e57d0f..ac9b1f8e4 100644 --- a/packages/ui-default/components/message/index.page.ts +++ b/packages/ui-default/components/message/index.page.ts @@ -46,12 +46,18 @@ const initWorkerMode = () => { console.log('Messages: using SharedWorker'); const worker = new SharedWorker(new URL('./worker', import.meta.url), { name: 'Hydro Messages Worker' }); worker.port.start(); + window.addEventListener('beforeunload', () => { + worker.port.postMessage({ type: 'unload' }); + }); worker.port.postMessage({ type: 'conn', path: endpoint, cookie: document.cookie }); worker.port.onmessage = async (message) => { if (process.env.NODE_ENV !== 'production') console.log('onmessage: ', message); const { payload, type } = message.data; if (type === 'message') { if (onmessage(payload)) worker.port.postMessage({ type: 'ack', id: payload.mdoc._id }); + } else if (type === 'open-page') { + console.log('opening page'); + window.open('/home/messages'); } }; }; diff --git a/packages/ui-default/components/message/worker.ts b/packages/ui-default/components/message/worker.ts index 38cae6cc4..073f3b6be 100644 --- a/packages/ui-default/components/message/worker.ts +++ b/packages/ui-default/components/message/worker.ts @@ -6,7 +6,7 @@ console.log('SharedWorker init'); let conn: ReconnectingWebsocket; let lcookie: string; -const ports: MessagePort[] = []; +let ports: MessagePort[] = []; interface RequestInitSharedConnPayload { type: 'conn'; cookie: string; @@ -16,7 +16,10 @@ interface RequestAckPayload { type: 'ack'; id: string; } -type RequestPayload = RequestInitSharedConnPayload | RequestAckPayload; +interface RequestUnloadPayload { + type: 'unload'; +} +type RequestPayload = RequestInitSharedConnPayload | RequestAckPayload | RequestUnloadPayload; const ack = {}; function broadcastMsg(message: any) { @@ -54,14 +57,15 @@ function initConn(path: string, port: MessagePort, cookie: any) { console.log('Notification permission denied'); return; } - const notification = new Notification( + // eslint-disable-next-line no-new + new Notification( payload.udoc.uname || 'Hydro Notification', { + tag: `message-${payload.mdoc._id}`, icon: payload.udoc.avatarUrl || '/android-chrome-192x192.png', body: payload.mdoc.content, }, ); - notification.onclick = () => window.open('/home/messages'); }, 5000); } }; @@ -74,6 +78,7 @@ onconnect = function (e) { port.addEventListener('message', (msg: { data: RequestPayload }) => { if (msg.data.type === 'conn') initConn(msg.data.path, port, msg.data.cookie); if (msg.data.type === 'ack') ack[msg.data.id](); + if (msg.data.type === 'unload') ports = ports.filter((i) => i !== port); }); port.start(); diff --git a/packages/ui-default/entry.js b/packages/ui-default/entry.js index f6eda4eef..a065836e7 100644 --- a/packages/ui-default/entry.js +++ b/packages/ui-default/entry.js @@ -27,6 +27,16 @@ console.log( `, ); +if ('serviceWorker' in navigator) { + window.addEventListener('load', () => { + navigator.serviceWorker.register(new URL('./service-worker', import.meta.url)).then((registration) => { + console.log('SW registered: ', registration); + }).catch((registrationError) => { + console.log('SW registration failed: ', registrationError); + }); + }); +} + document.addEventListener('DOMContentLoaded', async () => { window.UiContext = JSON.parse(window.UiContext); diff --git a/packages/ui-default/package.json b/packages/ui-default/package.json index c5a04f4e4..e204e385e 100644 --- a/packages/ui-default/package.json +++ b/packages/ui-default/package.json @@ -1,6 +1,6 @@ { "name": "@hydrooj/ui-default", - "version": "4.39.20", + "version": "4.39.21", "author": "undefined ", "license": "AGPL-3.0", "main": "hydro.js", @@ -31,6 +31,7 @@ "@types/qrcode": "^1.5.0", "@types/react-dom": "^18.0.6", "@types/redux-logger": "^3.0.9", + "@types/serviceworker": "^0.0.51", "@types/sharedworker": "^0.0.80", "@vscode/codicons": "^0.0.32", "autoprefixer": "^10.4.8", diff --git a/packages/ui-default/service-worker.ts b/packages/ui-default/service-worker.ts new file mode 100644 index 000000000..c06bbc787 --- /dev/null +++ b/packages/ui-default/service-worker.ts @@ -0,0 +1,14 @@ +/// +/* global clients */ +// eslint-disable-next-line no-restricted-globals +addEventListener('notificationclick', (event) => { + console.log('On notification click: ', event.notification.tag); + event.notification.close(); + if (!event.notification.tag.startsWith('message-')) return; + event.waitUntil(clients.matchAll({ type: 'window' }).then((clientList) => { + for (const client of clientList) { + if (client.url === '/home/messages' && 'focus' in client) return client.focus(); + } + if (clients.openWindow) clients.openWindow('/home/messages'); + })); +});