Промежуточный комит версии в которой ну хоть какието тестовые уведомления приходят. Но пока ещё вебпуш не работает
135 lines
4.0 KiB
JavaScript
135 lines
4.0 KiB
JavaScript
const LS_KEY = 'shine-ui-webpush-subscription-v1';
|
|
|
|
function urlBase64ToUint8Array(base64String) {
|
|
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;
|
|
}
|
|
|
|
export async function initPwaPush({ authService, onLog = null }) {
|
|
const log = (entry) => {
|
|
if (typeof onLog === 'function') onLog(entry);
|
|
};
|
|
|
|
if (!('serviceWorker' in navigator) || !('PushManager' in window)) {
|
|
log({
|
|
level: 'warn',
|
|
source: 'web-push',
|
|
message: 'Web Push недоступен: нет serviceWorker или PushManager',
|
|
});
|
|
return;
|
|
}
|
|
|
|
const vapidPublicKey = window.__SHINE_WEBPUSH_VAPID_PUBLIC_KEY__ || '';
|
|
if (!vapidPublicKey) {
|
|
log({
|
|
level: 'warn',
|
|
source: 'web-push',
|
|
message: 'Web Push отключен: не задан публичный VAPID ключ',
|
|
});
|
|
return;
|
|
}
|
|
|
|
try {
|
|
const registration = await navigator.serviceWorker.register('./firebase-messaging-sw.js');
|
|
log({
|
|
level: 'info',
|
|
source: 'web-push',
|
|
message: 'Service Worker зарегистрирован',
|
|
details: { scope: registration.scope },
|
|
});
|
|
|
|
const permission = await Notification.requestPermission();
|
|
if (permission !== 'granted') {
|
|
log({
|
|
level: 'warn',
|
|
source: 'web-push',
|
|
message: `Разрешение на уведомления: ${permission}`,
|
|
});
|
|
return;
|
|
}
|
|
log({
|
|
level: 'info',
|
|
source: 'web-push',
|
|
message: 'Разрешение на уведомления получено',
|
|
});
|
|
|
|
let sub = await registration.pushManager.getSubscription();
|
|
let isNewSubscription = false;
|
|
if (!sub) {
|
|
sub = await registration.pushManager.subscribe({
|
|
userVisibleOnly: true,
|
|
applicationServerKey: urlBase64ToUint8Array(vapidPublicKey),
|
|
});
|
|
isNewSubscription = true;
|
|
}
|
|
log({
|
|
level: 'info',
|
|
source: 'web-push',
|
|
message: isNewSubscription ? 'Создана новая push-подписка' : 'Найдена существующая push-подписка',
|
|
});
|
|
|
|
const serialized = JSON.stringify(sub);
|
|
const prevSerialized = localStorage.getItem(LS_KEY);
|
|
if (prevSerialized !== serialized) {
|
|
localStorage.setItem(LS_KEY, serialized);
|
|
log({
|
|
level: 'info',
|
|
source: 'web-push',
|
|
message: 'Push-подписка изменилась относительно прошлого запуска',
|
|
});
|
|
} else {
|
|
log({
|
|
level: 'info',
|
|
source: 'web-push',
|
|
message: 'Push-подписка не изменилась, но в MVP включена принудительная отправка на сервер',
|
|
});
|
|
}
|
|
|
|
const json = sub.toJSON();
|
|
const endpoint = json.endpoint || '';
|
|
const p256dhKey = json.keys?.p256dh || '';
|
|
const authKey = json.keys?.auth || '';
|
|
if (!endpoint || !p256dhKey || !authKey) {
|
|
log({
|
|
level: 'warn',
|
|
source: 'web-push',
|
|
message: 'Подписка неполная: endpoint/p256dh/auth отсутствуют',
|
|
});
|
|
return;
|
|
}
|
|
|
|
log({
|
|
level: 'info',
|
|
source: 'web-push',
|
|
message: 'Push-токен получен, отправка на сервер',
|
|
details: { endpoint },
|
|
});
|
|
|
|
await authService.upsertPushToken({
|
|
endpoint,
|
|
p256dhKey,
|
|
authKey,
|
|
platform: 'web',
|
|
userAgent: navigator.userAgent || '',
|
|
});
|
|
log({
|
|
level: 'info',
|
|
source: 'web-push',
|
|
message: 'Push-подписка успешно отправлена на сервер',
|
|
});
|
|
} catch (error) {
|
|
log({
|
|
level: 'error',
|
|
source: 'web-push',
|
|
message: 'Ошибка инициализации Web Push',
|
|
details: error?.message || 'unknown',
|
|
});
|
|
}
|
|
}
|