diff --git a/frontend/app.js b/frontend/app.js index e457ee7..4a080e5 100644 --- a/frontend/app.js +++ b/frontend/app.js @@ -243,6 +243,58 @@ function _registerSW() { }); } +// ========== VAPID / Push subscription ========== + +async function _fetchVapidPublicKey() { + try { + const res = await fetch('/api/vapid-public-key'); + if (!res.ok) { + console.warn('[baton] /api/vapid-public-key returned', res.status); + return null; + } + const data = await res.json(); + return data.vapid_public_key || null; + } catch (err) { + console.warn('[baton] Failed to fetch VAPID public key:', err); + return null; + } +} + +function _urlBase64ToUint8Array(base64String) { + const padding = '='.repeat((4 - (base64String.length % 4)) % 4); + const base64 = (base64String + padding).replace(/-/g, '+').replace(/_/g, '/'); + const raw = atob(base64); + const output = new Uint8Array(raw.length); + for (let i = 0; i < raw.length; i++) { + output[i] = raw.charCodeAt(i); + } + return output; +} + +async function _initPushSubscription(vapidPublicKey) { + if (!vapidPublicKey) { + console.warn('[baton] VAPID public key not available — push subscription skipped'); + return; + } + if (!('serviceWorker' in navigator) || !('PushManager' in window)) { + return; + } + try { + const registration = await navigator.serviceWorker.ready; + const existing = await registration.pushManager.getSubscription(); + if (existing) return; + const applicationServerKey = _urlBase64ToUint8Array(vapidPublicKey); + const subscription = await registration.pushManager.subscribe({ + userVisibleOnly: true, + applicationServerKey, + }); + _storage.setItem('baton_push_subscription', JSON.stringify(subscription)); + console.info('[baton] Push subscription created'); + } catch (err) { + console.warn('[baton] Push subscription failed:', err); + } +} + // ========== Init ========== function _init() { @@ -269,6 +321,11 @@ function _init() { } else { _showOnboarding(); } + + // Fire-and-forget: fetch VAPID key from API and subscribe to push (non-blocking) + _fetchVapidPublicKey().then(_initPushSubscription).catch((err) => { + console.warn('[baton] Push init error:', err); + }); } document.addEventListener('DOMContentLoaded', () => {