/* eslint-disable no-restricted-globals */ /// /// /// import ReconnectingWebsocket from 'reconnecting-websocket'; console.log('SharedWorker init'); let conn: ReconnectingWebsocket; let lcookie: string; let ports: MessagePort[] = []; interface RequestInitSharedConnPayload { type: 'conn'; cookie: string; path: string; } interface RequestAckPayload { type: 'ack'; id: string; } interface RequestUnloadPayload { type: 'unload'; } type RequestPayload = RequestInitSharedConnPayload | RequestAckPayload | RequestUnloadPayload; const ack = {}; function broadcastMsg(message: any) { for (const p of ports) p.postMessage(message); } function initConn(path: string, port: MessagePort, cookie: any) { if (cookie !== lcookie) conn?.close(); else if (conn && conn.readyState === conn.OPEN) return; lcookie = cookie; console.log('Init connection for', path); conn = new ReconnectingWebsocket(path); ports.push(port); conn.onopen = () => conn.send(cookie); conn.onerror = () => broadcastMsg({ type: 'error' }); conn.onclose = (ev) => broadcastMsg({ type: 'close', error: ev.reason }); conn.onmessage = (message) => { if (process.env.NODE_ENV !== 'production') console.log('SharedWorker.port.onmessage: ', message); const payload = JSON.parse(message.data); if (payload.event === 'auth') { if (['PermissionError', 'PrivilegeError'].includes(payload.error)) { broadcastMsg({ type: 'close', error: payload.error }); conn.close(); } else { console.log('Connected to', path); broadcastMsg({ type: 'open' }); } } else { broadcastMsg({ type: 'message', payload }); let acked = false; ack[payload.mdoc.id] = () => { acked = true; }; setTimeout(() => { delete ack[payload.mdoc.id]; if (acked) return; if (Notification?.permission !== 'granted') { console.log('Notification permission denied'); return; } // 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, }, ); }, 5000); } }; } onconnect = function (e) { // eslint-disable-line no-undef const port = e.ports[0]; 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(); };