talk2me/static/service-worker.js
Adolfo Delorenzo 77f31cd694 Update frontend branding from 'Voice Language Translator' to 'Talk2Me'
- Updated page title in index.html
- Updated main heading in index.html
- Updated PWA manifest name
- Updated service worker comment

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-03 08:59:00 -06:00

185 lines
4.9 KiB
JavaScript

// Service Worker for Talk2Me PWA
const CACHE_NAME = 'voice-translator-v1';
const ASSETS_TO_CACHE = [
'/',
'/static/css/styles.css',
'/static/js/dist/app.js',
'/static/icons/icon-192x192.png',
'/static/icons/icon-512x512.png',
'/static/icons/favicon.ico',
'https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css',
'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css'
];
// 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) => {
if (!event.data) {
return;
}
const data = event.data.json();
const options = {
body: data.body || 'New translation available',
icon: data.icon || '/static/icons/icon-192x192.png',
badge: data.badge || '/static/icons/icon-192x192.png',
vibrate: [100, 50, 100],
tag: data.tag || 'talk2me-notification',
requireInteraction: false,
silent: false,
data: {
url: data.url || '/',
...data.data
},
actions: [
{
action: 'view',
title: 'View',
icon: '/static/icons/icon-192x192.png'
},
{
action: 'close',
title: 'Close'
}
]
};
event.waitUntil(
self.registration.showNotification(data.title || 'Voice Translator', options)
);
});
// Handle notification click
self.addEventListener('notificationclick', (event) => {
event.notification.close();
if (event.action === 'close') {
return;
}
const urlToOpen = event.notification.data.url || '/';
event.waitUntil(
clients.matchAll({
type: 'window',
includeUncontrolled: true
}).then((windowClients) => {
// Check if there's already a window/tab with the app open
for (let client of windowClients) {
if (client.url === urlToOpen && 'focus' in client) {
return client.focus();
}
}
// If not, open a new window/tab
if (clients.openWindow) {
return clients.openWindow(urlToOpen);
}
})
);
});
// Handle periodic background sync
self.addEventListener('periodicsync', (event) => {
if (event.tag === 'translation-updates') {
event.waitUntil(checkForUpdates());
}
});
async function checkForUpdates() {
// Check for app updates or send usage statistics
try {
const response = await fetch('/api/check-updates');
if (response.ok) {
const data = await response.json();
if (data.hasUpdate) {
self.registration.showNotification('Update Available', {
body: 'A new version of Voice Translator is available!',
icon: '/static/icons/icon-192x192.png',
badge: '/static/icons/icon-192x192.png',
tag: 'update-notification'
});
}
}
} catch (error) {
console.error('Failed to check for updates:', error);
}
}