// 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) ); });