( event: PushSubscriptionChangeEvent, )
| 66 | }); |
| 67 | |
| 68 | async function handlePushSubscriptionChange( |
| 69 | event: PushSubscriptionChangeEvent, |
| 70 | ): Promise<void> { |
| 71 | // Prefer the application server key the browser already negotiated, so |
| 72 | // we don't depend on the React side delivering a fresh VAPID key into |
| 73 | // the worker. Fall back to the old subscription's options when the new |
| 74 | // one is null (the browser revoked without auto-renewing). |
| 75 | const applicationServerKey = |
| 76 | event.newSubscription?.options.applicationServerKey ?? |
| 77 | event.oldSubscription?.options.applicationServerKey; |
| 78 | if (!applicationServerKey) { |
| 79 | return; |
| 80 | } |
| 81 | |
| 82 | const subscription = |
| 83 | event.newSubscription ?? |
| 84 | (await self.registration.pushManager.subscribe({ |
| 85 | userVisibleOnly: true, |
| 86 | applicationServerKey, |
| 87 | })); |
| 88 | |
| 89 | const json = subscription.toJSON(); |
| 90 | if (!json.endpoint || !json.keys) { |
| 91 | return; |
| 92 | } |
| 93 | |
| 94 | await fetch("/api/v2/users/me/webpush/subscription", { |
| 95 | method: "POST", |
| 96 | headers: { "Content-Type": "application/json" }, |
| 97 | credentials: "include", |
| 98 | body: JSON.stringify({ |
| 99 | endpoint: json.endpoint, |
| 100 | auth_key: json.keys.auth, |
| 101 | p256dh_key: json.keys.p256dh, |
| 102 | }), |
| 103 | }); |
| 104 | |
| 105 | if (event.oldSubscription) { |
| 106 | await fetch("/api/v2/users/me/webpush/subscription", { |
| 107 | method: "DELETE", |
| 108 | headers: { "Content-Type": "application/json" }, |
| 109 | credentials: "include", |
| 110 | body: JSON.stringify({ endpoint: event.oldSubscription.endpoint }), |
| 111 | }); |
| 112 | } |
| 113 | } |
| 114 | |
| 115 | // Handle notification click — navigate to the specific chat or agents page. |
| 116 | self.addEventListener("notificationclick", (event) => { |
no test coverage detected