|
| 1 | +import { writable, readable } from 'svelte/store'; |
| 2 | +import { browser } from '$app/environment'; |
| 3 | + |
| 4 | +/** Reactive online/offline status */ |
| 5 | +export const isOnline = readable(true, (set) => { |
| 6 | + if (!browser) return; |
| 7 | + set(navigator.onLine); |
| 8 | + const on = () => set(true); |
| 9 | + const off = () => set(false); |
| 10 | + window.addEventListener('online', on); |
| 11 | + window.addEventListener('offline', off); |
| 12 | + return () => { window.removeEventListener('online', on); window.removeEventListener('offline', off); }; |
| 13 | +}); |
| 14 | + |
| 15 | +/** Push notification permission state */ |
| 16 | +export const pushPermission = writable<NotificationPermission>('default'); |
| 17 | + |
| 18 | +export async function requestPushPermission(): Promise<boolean> { |
| 19 | + if (!browser || !('Notification' in window)) return false; |
| 20 | + const result = await Notification.requestPermission(); |
| 21 | + pushPermission.set(result); |
| 22 | + return result === 'granted'; |
| 23 | +} |
| 24 | + |
| 25 | +/** Subscribe to push notifications via the service worker */ |
| 26 | +export async function subscribePush(vapidPublicKey: string): Promise<PushSubscription | null> { |
| 27 | + if (!browser || !('serviceWorker' in navigator) || !('PushManager' in window)) return null; |
| 28 | + const reg = await navigator.serviceWorker.ready; |
| 29 | + const existing = await reg.pushManager.getSubscription(); |
| 30 | + if (existing) return existing; |
| 31 | + return reg.pushManager.subscribe({ |
| 32 | + userVisibleOnly: true, |
| 33 | + applicationServerKey: urlBase64ToUint8Array(vapidPublicKey) |
| 34 | + }); |
| 35 | +} |
| 36 | + |
| 37 | +function urlBase64ToUint8Array(base64: string): Uint8Array { |
| 38 | + const padding = '='.repeat((4 - (base64.length % 4)) % 4); |
| 39 | + const b64 = (base64 + padding).replace(/-/g, '+').replace(/_/g, '/'); |
| 40 | + const raw = atob(b64); |
| 41 | + return Uint8Array.from([...raw].map((c) => c.charCodeAt(0))); |
| 42 | +} |
0 commit comments