diff options
Diffstat (limited to 'packages/client/src/scripts/initialize-sw.ts')
| -rw-r--r-- | packages/client/src/scripts/initialize-sw.ts | 68 |
1 files changed, 68 insertions, 0 deletions
diff --git a/packages/client/src/scripts/initialize-sw.ts b/packages/client/src/scripts/initialize-sw.ts new file mode 100644 index 0000000000..d6dbd5dbd4 --- /dev/null +++ b/packages/client/src/scripts/initialize-sw.ts @@ -0,0 +1,68 @@ +import { instance } from '@/instance'; +import { $i } from '@/account'; +import { api } from '@/os'; +import { lang } from '@/config'; + +export async function initializeSw() { + if (instance.swPublickey && + ('serviceWorker' in navigator) && + ('PushManager' in window) && + $i && $i.token) { + navigator.serviceWorker.register(`/sw.js`); + + navigator.serviceWorker.ready.then(registration => { + registration.active?.postMessage({ + msg: 'initialize', + lang, + }); + // SEE: https://developer.mozilla.org/en-US/docs/Web/API/PushManager/subscribe#Parameters + registration.pushManager.subscribe({ + userVisibleOnly: true, + applicationServerKey: urlBase64ToUint8Array(instance.swPublickey) + }).then(subscription => { + function encode(buffer: ArrayBuffer | null) { + return btoa(String.fromCharCode.apply(null, new Uint8Array(buffer))); + } + + // Register + api('sw/register', { + endpoint: subscription.endpoint, + auth: encode(subscription.getKey('auth')), + publickey: encode(subscription.getKey('p256dh')) + }); + }) + // When subscribe failed + .catch(async (err: Error) => { + // 通知が許可されていなかったとき + if (err.name === 'NotAllowedError') { + return; + } + + // 違うapplicationServerKey (または gcm_sender_id)のサブスクリプションが + // 既に存在していることが原因でエラーになった可能性があるので、 + // そのサブスクリプションを解除しておく + const subscription = await registration.pushManager.getSubscription(); + if (subscription) subscription.unsubscribe(); + }); + }); + } +} + +/** + * Convert the URL safe base64 string to a Uint8Array + * @param base64String base64 string + */ +function urlBase64ToUint8Array(base64String: string): Uint8Array { + const padding = '='.repeat((4 - base64String.length % 4) % 4); + const base64 = (base64String + padding) + .replace(/-/g, '+') + .replace(/_/g, '/'); + + const rawData = window.atob(base64); + const outputArray = new Uint8Array(rawData.length); + + for (let i = 0; i < rawData.length; ++i) { + outputArray[i] = rawData.charCodeAt(i); + } + return outputArray; +} |