talk2me/static/service-worker.js
2025-04-05 11:50:31 -06:00

116 lines
3.1 KiB
JavaScript

// Service Worker for Voice Language Translator PWA
const CACHE_NAME = 'voice-translator-v1';
const ASSETS_TO_CACHE = [
'/',
'/static/css/styles.css',
'/static/js/app.js',
'/static/icons/icon-192x192.png',
'/static/icons/icon-512x512.png',
'/static/icons/favicon.ico'
];
// Install event - cache essential assets
self.addEventListener('install', (event) => {
event.waitUntil(
caches.open(CACHE_NAME)
.then((cache) => {
console.log('Service Worker: Caching files');
return cache.addAll(ASSETS_TO_CACHE);
})
.then(() => self.skipWaiting())
);
});
// Activate event - clean up old caches
self.addEventListener('activate', (event) => {
event.waitUntil(
caches.keys().then((cacheNames) => {
return Promise.all(
cacheNames.map((name) => {
if (name !== CACHE_NAME) {
console.log('Service Worker: Clearing old cache');
return caches.delete(name);
}
})
);
})
);
});
// Fetch event - serve cached content when offline
self.addEventListener('fetch', (event) => {
// Skip cross-origin requests
if (!event.request.url.startsWith(self.location.origin)) {
return;
}
// Skip API calls - we don't want to cache those
if (event.request.url.includes('/transcribe') ||
event.request.url.includes('/translate') ||
event.request.url.includes('/speak') ||
event.request.url.includes('/get_audio/')) {
return;
}
event.respondWith(
caches.match(event.request)
.then((cachedResponse) => {
// Return cached response if available
if (cachedResponse) {
return cachedResponse;
}
// Otherwise fetch from network
return fetch(event.request)
.then((response) => {
// Don't cache if response is not valid
if (!response || response.status !== 200 || response.type !== 'basic') {
return response;
}
// Clone the response since it can only be consumed once
const responseToCache = response.clone();
caches.open(CACHE_NAME)
.then((cache) => {
cache.put(event.request, responseToCache);
});
return response;
})
.catch(() => {
// If network fetch fails and it's a document request, return fallback
if (event.request.mode === 'navigate') {
return caches.match('/');
}
});
})
);
});
// Handle push notifications
self.addEventListener('push', (event) => {
const data = event.data.json();
const options = {
body: data.body || 'New translation available',
icon: '/static/icons/icon-192x192.png',
badge: '/static/icons/badge-72x72.png',
vibrate: [100, 50, 100],
data: {
url: data.url || '/'
}
};
event.waitUntil(
self.registration.showNotification(data.title || 'Voice Translator', options)
);
});
// Handle notification click
self.addEventListener('notificationclick', (event) => {
event.notification.close();
event.waitUntil(
clients.openWindow(event.notification.data.url)
);
});