Spaces:
Running
Running
| /** | |
| * Service Worker for PWA | |
| * Handles offline functionality and caching | |
| */ | |
| const CACHE_NAME = 'mipesca-v2'; | |
| const STATIC_CACHE = [ | |
| './', | |
| 'index.html', | |
| 'css/styles.css', | |
| 'js/app.js', | |
| 'js/db.js', | |
| 'js/geolocation.js', | |
| 'js/api.js', | |
| 'js/sync.js', | |
| 'js/components/home.js', | |
| 'js/components/species-selector.js', | |
| 'js/components/capture-form.js', | |
| 'js/components/confirmation.js', | |
| 'js/components/history.js', | |
| 'js/components/info.js', | |
| 'manifest.json', | |
| 'https://unpkg.com/dexie@3.2.4/dist/dexie.min.js' | |
| ]; | |
| // Install event - cache static assets | |
| self.addEventListener('install', (event) => { | |
| console.log('Service Worker installing...'); | |
| event.waitUntil( | |
| caches.open(CACHE_NAME) | |
| .then((cache) => { | |
| console.log('Caching static assets'); | |
| return cache.addAll(STATIC_CACHE); | |
| }) | |
| .then(() => self.skipWaiting()) | |
| ); | |
| }); | |
| // Activate event - clean up old caches | |
| self.addEventListener('activate', (event) => { | |
| console.log('Service Worker activating...'); | |
| event.waitUntil( | |
| caches.keys().then((cacheNames) => { | |
| return Promise.all( | |
| cacheNames.map((cacheName) => { | |
| if (cacheName !== CACHE_NAME) { | |
| console.log('Deleting old cache:', cacheName); | |
| return caches.delete(cacheName); | |
| } | |
| }) | |
| ); | |
| }).then(() => self.clients.claim()) | |
| ); | |
| }); | |
| // Fetch event - serve from cache, fallback to network | |
| self.addEventListener('fetch', (event) => { | |
| const { request } = event; | |
| const url = new URL(request.url); | |
| // API requests - network first, then cache | |
| if (url.pathname.startsWith('/api/')) { | |
| event.respondWith( | |
| fetch(request) | |
| .then((response) => { | |
| // Clone response to cache it | |
| const responseClone = response.clone(); | |
| caches.open(CACHE_NAME).then((cache) => { | |
| cache.put(request, responseClone); | |
| }); | |
| return response; | |
| }) | |
| .catch(() => { | |
| // If network fails, try cache | |
| return caches.match(request); | |
| }) | |
| ); | |
| return; | |
| } | |
| // Static assets - cache first, then network | |
| event.respondWith( | |
| caches.match(request) | |
| .then((cachedResponse) => { | |
| if (cachedResponse) { | |
| return cachedResponse; | |
| } | |
| return fetch(request) | |
| .then((response) => { | |
| // Don't cache non-successful responses | |
| if (!response || response.status !== 200 || response.type === 'error') { | |
| return response; | |
| } | |
| // Clone response to cache it | |
| const responseClone = response.clone(); | |
| caches.open(CACHE_NAME).then((cache) => { | |
| cache.put(request, responseClone); | |
| }); | |
| return response; | |
| }); | |
| }) | |
| .catch(() => { | |
| // Return offline page if available | |
| if (request.mode === 'navigate') { | |
| return caches.match('/index.html'); | |
| } | |
| }) | |
| ); | |
| }); | |
| // Background sync for captures | |
| self.addEventListener('sync', (event) => { | |
| if (event.tag === 'sync-captures') { | |
| console.log('Background sync triggered'); | |
| event.waitUntil( | |
| // Notify clients to sync | |
| self.clients.matchAll().then((clients) => { | |
| clients.forEach((client) => { | |
| client.postMessage({ | |
| type: 'BACKGROUND_SYNC', | |
| action: 'sync-captures' | |
| }); | |
| }); | |
| }) | |
| ); | |
| } | |
| }); | |