diff options
| author | Adam Soltys <[email protected]> | 2026-10-22 10:32:22 -0700 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2026-10-22 10:32:22 -0700 |
| commit | 1ea1784c4ad7d6715c0efdcd0078019c692eefe5 (patch) | |
| tree | e5f86cd28d103341114930444c3980cda72257ac /src/features | |
| parent | d59a7f0c9b32002ff23f74a2996b986cf1f0dd05 (diff) | |
| download | coinosv3-1ea1784c4ad7d6715c0efdcd0078019c692eefe5.tar.gz coinosv3-1ea1784c4ad7d6715c0efdcd0078019c692eefe5.zip | |
iPhone: a push subscription iOS dropped is made again when the app opens or comes back
WebKit removes a subscription after three pushes that showed no
notification (743011c stops new strikes, but a wallet already struck out
stayed deaf): background stayed on, getSubscription() came back empty and
refreshRegistration gave up, so NWC requests stopped waking the closed app
until the switch was toggled (reported by PullCap). It now subscribes again
(also when the VAPID key changed) and re-registers with the notifier, on
start and whenever the app returns to the screen.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01K5xtiFrkFVsrkWx6JDQjiT
Diffstat (limited to 'src/features')
| -rw-r--r-- | src/features/nwc.js | 24 |
1 files changed, 21 insertions, 3 deletions
diff --git a/src/features/nwc.js b/src/features/nwc.js index ec79081..9c71a7f 100644 --- a/src/features/nwc.js +++ b/src/features/nwc.js @@ -822,6 +822,25 @@ export function nwcFeature(ctx) { // wrong keys — background wake-ups silently die the first time a // connection is recreated. Debounced; the server replaces by endpoint. let regTimer = null; + // The browser's subscription, made again when it's gone: iOS drops it after + // three pushes that showed no notification (and a key rotation strands an + // old one), and nothing else re-arms a wallet whose `background` is still on. + async function currentSub() { + const reg = await navigator.serviceWorker.ready; + const { publicKey } = await (await fetch(`${NOTIFIER}/vapid`)).json(); + const want = b64ToBytes(publicKey); + let sub = await reg.pushManager.getSubscription(); + if (sub) { + let have = []; + try { have = new Uint8Array(sub.options.applicationServerKey || []); } catch {} + if (have.length === want.length && have.every((b, i) => b === want[i])) return sub.toJSON(); + try { await sub.unsubscribe(); } catch {} + } + if (typeof Notification === 'undefined' || Notification.permission !== 'granted') return null; + sub = await reg.pushManager.subscribe({ userVisibleOnly: true, applicationServerKey: want }); + dlog('nwc: push subscription was gone, made a new one'); + return sub.toJSON(); + } function refreshRegistration() { if (!load().background) return; if (typeof navigator === 'undefined' || !('serviceWorker' in navigator)) return; @@ -831,8 +850,7 @@ export function nwcFeature(ctx) { const pks = watchPks(); if (!pks.length) return; const up2 = upEndpoint(); - const sub = up2 ? { endpoint: up2, unifiedpush: true } - : await (await navigator.serviceWorker.ready).pushManager.getSubscription().then((x) => x && x.toJSON()); + const sub = up2 ? { endpoint: up2, unifiedpush: true } : await currentSub(); if (!sub) return; await fetch(`${NOTIFIER}/register`, { method: 'POST', headers: { 'content-type': 'application/json' }, @@ -949,7 +967,7 @@ export function nwcFeature(ctx) { if (typeof window !== 'undefined') { window.addEventListener('online', () => listen()); document.addEventListener('visibilitychange', () => { - if (document.visibilityState === 'visible' && conns().length) listen(); + if (document.visibilityState === 'visible' && conns().length) { listen(); refreshRegistration(); } }); } } |
