import { getToken } from '../Utils'; /** Převede base64url VAPID klíč na Uint8Array pro PushManager. */ function urlBase64ToUint8Array(base64String: string): Uint8Array { const padding = '='.repeat((4 - (base64String.length % 4)) % 4); const base64 = (base64String + padding).replace(/-/g, '+').replace(/_/g, '/'); const rawData = atob(base64); const outputArray = new Uint8Array(rawData.length); for (let i = 0; i < rawData.length; ++i) { outputArray[i] = rawData.charCodeAt(i); } return outputArray; } /** Helper pro autorizované API volání na push endpointy. */ async function pushApiFetch(path: string, options: RequestInit = {}): Promise { const token = getToken(); return fetch(`/api/notifications/push${path}`, { ...options, headers: { 'Content-Type': 'application/json', ...(token ? { Authorization: `Bearer ${token}` } : {}), ...options.headers, }, }); } /** * Zaregistruje service worker, přihlásí se k push notifikacím * a odešle subscription na server. */ export async function subscribeToPush(reminderTime: string): Promise { if (!('serviceWorker' in navigator) || !('PushManager' in window)) { console.warn('Push notifikace nejsou v tomto prohlížeči podporovány'); return false; } try { // Registrace service workeru const registration = await navigator.serviceWorker.register('/sw.js'); await navigator.serviceWorker.ready; // Vyžádání oprávnění const permission = await Notification.requestPermission(); if (permission !== 'granted') { console.warn('Push notifikace: oprávnění zamítnuto'); return false; } // Získání VAPID veřejného klíče ze serveru const vapidResponse = await pushApiFetch('/vapidKey'); if (!vapidResponse.ok) { console.error('Push notifikace: nepodařilo se získat VAPID klíč'); return false; } const { key: vapidPublicKey } = await vapidResponse.json(); // Přihlášení k push const subscription = await registration.pushManager.subscribe({ userVisibleOnly: true, applicationServerKey: urlBase64ToUint8Array(vapidPublicKey) as BufferSource, }); // Odeslání subscription na server const response = await pushApiFetch('/subscribe', { method: 'POST', body: JSON.stringify({ subscription: subscription.toJSON(), reminderTime, }), }); if (!response.ok) { console.error('Push notifikace: nepodařilo se odeslat subscription na server'); return false; } console.log('Push notifikace: úspěšně přihlášeno k připomínkám v', reminderTime); return true; } catch (error) { console.error('Push notifikace: chyba při registraci', error); return false; } } /** * Odhlásí se z push notifikací a informuje server. */ export async function unsubscribeFromPush(): Promise { if (!('serviceWorker' in navigator)) { return; } try { const registration = await navigator.serviceWorker.getRegistration('/sw.js'); if (registration) { const subscription = await registration.pushManager.getSubscription(); if (subscription) { await subscription.unsubscribe(); } } await pushApiFetch('/unsubscribe', { method: 'POST' }); console.log('Push notifikace: úspěšně odhlášeno z připomínek'); } catch (error) { console.error('Push notifikace: chyba při odhlášení', error); } }