diff --git a/public/index.html b/public/index.html index fe61449..e9c513e 100644 --- a/public/index.html +++ b/public/index.html @@ -11,7 +11,7 @@ - + @@ -23,20 +23,5 @@
- - - diff --git a/public/manifest.json b/public/manifest.json index dd134ea..ee1b02e 100644 --- a/public/manifest.json +++ b/public/manifest.json @@ -2,6 +2,7 @@ "short_name": "Time Tracker", "name": "Ficosa Time Tracker App", "description": "Track your work hours and manage your time efficiently", + "id": "/time-tracker/", "icons": [ { "src": "favicon.ico", @@ -11,12 +12,26 @@ { "src": "logo192.png", "type": "image/png", - "sizes": "192x192" + "sizes": "192x192", + "purpose": "any" + }, + { + "src": "logo192.png", + "type": "image/png", + "sizes": "192x192", + "purpose": "maskable" }, { "src": "logo512.png", "type": "image/png", - "sizes": "512x512" + "sizes": "512x512", + "purpose": "any" + }, + { + "src": "logo512.png", + "type": "image/png", + "sizes": "512x512", + "purpose": "maskable" } ], "start_url": ".", diff --git a/public/service-worker.js b/public/service-worker.js index 7f3be84..ddf340d 100644 --- a/public/service-worker.js +++ b/public/service-worker.js @@ -1,37 +1,67 @@ -const CACHE_NAME = 'time-tracker-app-v1'; +const CACHE_NAME = 'time-tracker-app-v2'; const urlsToCache = [ '/', - '/static/js/bundle.js', - '/static/css/main.css', + '/index.html', '/manifest.json', '/favicon.ico', - '/logo_ficosa.png' + '/logo192.png', + '/logo512.png' ]; -// Install event - cache essential assets +// Install event - cache essential static assets self.addEventListener('install', (event) => { + // Skip waiting to activate immediately + self.skipWaiting(); + event.waitUntil( caches.open(CACHE_NAME) .then((cache) => { console.log('Opened cache'); + // Use addAll for guaranteed files. If these fail, SW won't install. + // We omit JS/CSS because CRA uses hashed filenames in production. return cache.addAll(urlsToCache); }) ); }); -// Fetch event - serve cached content when offline +// Fetch event - Stale-while-revalidate strategy for most requests self.addEventListener('fetch', (event) => { + // Only handle GET requests + if (event.request.method !== 'GET') return; + + // Skip cross-origin requests + if (!event.request.url.startsWith(self.location.origin)) return; + event.respondWith( caches.match(event.request) - .then((response) => { - // Return cached version or fetch from network - return response || fetch(event.request); + .then((cachedResponse) => { + const fetchPromise = fetch(event.request).then((networkResponse) => { + // Dynamically cache successful GET requests + if (networkResponse && networkResponse.status === 200) { + const responseToCache = networkResponse.clone(); + caches.open(CACHE_NAME) + .then((cache) => { + cache.put(event.request, responseToCache); + }); + } + return networkResponse; + }).catch(() => { + // If network fails and we have no cache, return the cached index.html for navigation requests (SPA fallback) + if (event.request.mode === 'navigate') { + return caches.match('/'); + } + }); + + return cachedResponse || fetchPromise; }) ); }); // Activate event - clean up old caches self.addEventListener('activate', (event) => { + // Take control of all clients immediately + event.waitUntil(self.clients.claim()); + event.waitUntil( caches.keys().then((cacheNames) => { return Promise.all( diff --git a/src/index.js b/src/index.js index c962028..a577459 100644 --- a/src/index.js +++ b/src/index.js @@ -7,7 +7,8 @@ import reportWebVitals from './reportWebVitals'; // Register service worker for PWA functionality if ('serviceWorker' in navigator) { window.addEventListener('load', () => { - navigator.serviceWorker.register('/service-worker.js') + const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`; + navigator.serviceWorker.register(swUrl) .then((registration) => { console.log('Service Worker registered: ', registration); })