184 lines
5.4 KiB
TypeScript
184 lines
5.4 KiB
TypeScript
export {}
|
|
// Импортируем workbox (v6 API)
|
|
import { precacheAndRoute } from 'workbox-precaching';
|
|
import { registerRoute } from 'workbox-routing';
|
|
import { StaleWhileRevalidate, CacheFirst } from 'workbox-strategies';
|
|
import { ExpirationPlugin } from 'workbox-expiration';
|
|
import { CacheableResponsePlugin } from 'workbox-cacheable-response';
|
|
|
|
// Отключаем шумное логирование Workbox
|
|
// Используем self.__WB_DISABLE_DEV_LOGS для отключения логирования в development
|
|
(self as any).__WB_DISABLE_DEV_LOGS = true;
|
|
|
|
// Типы для push уведомлений
|
|
interface NotificationAction {
|
|
action: string;
|
|
title: string;
|
|
icon?: string;
|
|
}
|
|
|
|
interface PushNotificationData {
|
|
title: string;
|
|
body: string;
|
|
icon?: string;
|
|
badge?: string;
|
|
url?: string;
|
|
tag?: string;
|
|
actions?: NotificationAction[];
|
|
}
|
|
|
|
interface PushEvent extends ExtendableEvent {
|
|
data: {
|
|
text(): string;
|
|
json(): any;
|
|
} | null;
|
|
}
|
|
|
|
// Precache all assets generated by the build process.
|
|
precacheAndRoute((self as any).__WB_MANIFEST);
|
|
|
|
// Cache images with a Cache First strategy
|
|
registerRoute(
|
|
({ request }) => request.destination === 'image',
|
|
new CacheFirst({
|
|
cacheName: 'images',
|
|
plugins: [
|
|
new ExpirationPlugin({
|
|
maxEntries: 60,
|
|
maxAgeSeconds: 30 * 24 * 60 * 60, // 30 Days
|
|
}),
|
|
new CacheableResponsePlugin({
|
|
statuses: [0, 200],
|
|
}),
|
|
],
|
|
}),
|
|
);
|
|
|
|
// Cache CSS, JS, and Web Worker requests with a Stale While Revalidate strategy
|
|
registerRoute(
|
|
({ request }) =>
|
|
request.destination === 'style' ||
|
|
request.destination === 'script' ||
|
|
request.destination === 'worker',
|
|
new StaleWhileRevalidate({
|
|
cacheName: 'static-resources',
|
|
}),
|
|
);
|
|
|
|
// Cache Google Fonts with a Cache First strategy
|
|
registerRoute(
|
|
({ request }) =>
|
|
request.url.includes('fonts.googleapis.com') ||
|
|
request.url.includes('fonts.gstatic.com'),
|
|
new CacheFirst({
|
|
cacheName: 'google-fonts',
|
|
plugins: [
|
|
new ExpirationPlugin({
|
|
maxEntries: 30,
|
|
maxAgeSeconds: 60 * 60 * 24 * 365, // 1 year
|
|
}),
|
|
new CacheableResponsePlugin({
|
|
statuses: [0, 200],
|
|
}),
|
|
],
|
|
}),
|
|
);
|
|
|
|
// Handle messages from the main thread
|
|
self.addEventListener('message', (event) => {
|
|
if (event.data && event.data.type === 'SKIP_WAITING') {
|
|
self.skipWaiting();
|
|
}
|
|
});
|
|
|
|
// Handle service worker activation
|
|
self.addEventListener('activate', () => {
|
|
// console.log отключен для уменьшения шума в консоли
|
|
|
|
// Take control of all pages immediately
|
|
(self as any).clients.claim();
|
|
});
|
|
|
|
// Handle service worker installation
|
|
self.addEventListener('install', () => {
|
|
// console.log отключен для уменьшения шума в консоли
|
|
|
|
// Skip waiting to activate immediately
|
|
(self as any).skipWaiting();
|
|
});
|
|
|
|
// Handle fetch events for offline functionality
|
|
self.addEventListener('fetch', () => {
|
|
// You can add custom fetch handling here if needed
|
|
// For now, let the default behavior handle requests
|
|
});
|
|
|
|
/**
|
|
* Обработка входящих push уведомлений
|
|
*/
|
|
self.addEventListener('push', (event: PushEvent) => {
|
|
console.log('Push уведомление получено:', event);
|
|
|
|
let notificationData: PushNotificationData;
|
|
|
|
try {
|
|
// Пытаемся извлечь данные из push уведомления
|
|
if (event.data) {
|
|
const rawData = event.data.text();
|
|
notificationData = JSON.parse(rawData);
|
|
} else {
|
|
console.log('Нет данных в push событии, используем fallback');
|
|
// Fallback уведомление
|
|
notificationData = {
|
|
title: 'Новое уведомление',
|
|
body: 'У вас есть новое уведомление',
|
|
icon: '/icons/icon-192x192.png',
|
|
badge: '/icons/icon-192x192.png',
|
|
};
|
|
}
|
|
} catch (error) {
|
|
console.error('Ошибка парсинга push данных:', error);
|
|
notificationData = {
|
|
title: 'Новое уведомление',
|
|
body: 'У вас есть новое уведомление',
|
|
icon: '/icons/icon-192x192.png',
|
|
badge: '/icons/icon-192x192.png',
|
|
};
|
|
}
|
|
|
|
// Показываем уведомление
|
|
const notificationOptions: NotificationOptions = {
|
|
body: notificationData.body,
|
|
icon: notificationData.icon || '/icons/icon-192x192.png',
|
|
badge: notificationData.badge || '/icons/icon-192x192.png',
|
|
tag: notificationData.tag || 'general',
|
|
data: {
|
|
url: notificationData.url || '/',
|
|
timestamp: Date.now(),
|
|
},
|
|
requireInteraction: false,
|
|
silent: false,
|
|
};
|
|
|
|
// Добавляем actions если поддерживаются
|
|
if (notificationData.actions && notificationData.actions.length > 0) {
|
|
(notificationOptions as any).actions = notificationData.actions;
|
|
}
|
|
|
|
console.log('Показываем уведомление с данными:', {
|
|
title: notificationData.title,
|
|
options: notificationOptions,
|
|
});
|
|
|
|
const showNotificationPromise = self.registration
|
|
.showNotification(notificationData.title, notificationOptions)
|
|
.then(() => {
|
|
console.log('Уведомление успешно показано');
|
|
})
|
|
.catch((error) => {
|
|
console.error('Ошибка показа уведомления:', error);
|
|
});
|
|
|
|
event.waitUntil(showNotificationPromise);
|
|
});
|