/* Geonet Console — PWA service worker (Fase B: install + login shell cache) */ var CACHE_VERSION = 'geonet-console-v3'; var PRECACHE_URLS = [ '/offline.html', '/css/app-ui.css', '/js/theme-init.js', '/js/theme.js', '/js/pwa-register.js', '/js/pwa-install.js', '/js/pwa-login-shell.js', '/js/ui-feedback.js', '/icons/icon.svg', '/icons/icon-maskable.svg', '/manifest.webmanifest' ]; var LOGIN_SHELL_PATHS = ['/login', '/password/forgot']; function shouldSkip(request) { if (request.method !== 'GET') { return true; } var url = new URL(request.url); if (url.origin !== self.location.origin) { return true; } if (url.pathname.indexOf('/api/') === 0) { return true; } if (url.pathname.indexOf('/audit/') === 0) { return true; } if (url.pathname.indexOf('/oauth/') === 0) { return true; } return false; } function isNavigation(request) { if (request.mode === 'navigate') { return true; } var accept = request.headers.get('accept') || ''; return accept.indexOf('text/html') !== -1; } function isLoginShellPath(pathname) { var path = pathname.replace(/\/$/, '') || '/'; return LOGIN_SHELL_PATHS.indexOf(path) !== -1; } function isStaticAsset(pathname) { return /\.(css|js|svg|webmanifest|png|jpg|jpeg|webp|woff2?)$/i.test(pathname) || pathname === '/offline.html' || pathname === '/manifest.webmanifest'; } function staleWhileRevalidate(request) { return caches.open(CACHE_VERSION).then(function (cache) { return cache.match(request).then(function (cached) { var networkFetch = fetch(request).then(function (response) { if (response && response.status === 200) { cache.put(request, response.clone()); } return response; }).catch(function () { return null; }); if (cached) { networkFetch.then(function () {}); return cached; } return networkFetch.then(function (response) { return response || caches.match('/offline.html'); }); }); }); } self.addEventListener('install', function (event) { event.waitUntil( caches.open(CACHE_VERSION).then(function (cache) { return cache.addAll(PRECACHE_URLS); }).then(function () { return self.skipWaiting(); }) ); }); self.addEventListener('activate', function (event) { event.waitUntil( caches.keys().then(function (keys) { return Promise.all( keys.filter(function (key) { return key.indexOf('geonet-console-') === 0 && key !== CACHE_VERSION; }).map(function (key) { return caches.delete(key); }) ); }).then(function () { return self.clients.claim(); }) ); }); self.addEventListener('fetch', function (event) { var request = event.request; if (shouldSkip(request)) { return; } var url = new URL(request.url); if (isNavigation(request)) { if (isLoginShellPath(url.pathname)) { event.respondWith(staleWhileRevalidate(request)); return; } event.respondWith( fetch(request).catch(function () { return caches.match('/offline.html'); }) ); return; } if (isStaticAsset(url.pathname)) { event.respondWith( caches.match(request).then(function (cached) { var networkFetch = fetch(request).then(function (response) { if (response && response.status === 200) { var copy = response.clone(); caches.open(CACHE_VERSION).then(function (cache) { cache.put(request, copy); }); } return response; }); return cached || networkFetch; }) ); } });