const CACHE_NAME = 'basspago-v1.0.0'; const urlsToCache = [ // Páginas principais '/', '/pix', '/pdv', '/conta-digital', '/desenvolvedores', '/precos', // Favicons '/favicon-16x16.png', '/apple-touch-icon.png', // Imagens críticas do hero/homepage '/src/lib/assets/backgroundSection2.png', '/src/lib/assets/phone-card.png', '/src/lib/assets/backgroundPDV.png', '/src/lib/assets/phone-qrcode.png', // Logos de parceiros (críticos para hero) '/src/lib/assets/marca-cambionet.png', '/src/lib/assets/marca-cazco.png', '/src/lib/assets/marca-cdl.png', '/src/lib/assets/marca-fecomercio-rs.png', '/src/lib/assets/marca-gramado-sumit.png', '/src/lib/assets/marca-hubsafe.png', '/src/lib/assets/marca-ic-globall.png', '/src/lib/assets/marca-ic-sindi.png', '/src/lib/assets/marca-jusfy.png', '/src/lib/assets/marca-sesc.png', // Outras imagens importantes '/src/lib/assets/cubes-plus.svg', '/src/lib/assets/iphone-pix-mockup.png', '/src/lib/assets/iphone-pix-mockup2.png', '/src/lib/assets/banking-interface-mockup2.png', '/src/lib/assets/qrcode-azul.png', '/src/lib/assets/copy-link-pagamento.png', // Ícones e SVGs críticos '/src/lib/assets/pix-e-ted-azul.svg', '/src/lib/assets/pagamentos-azul.svg', '/src/lib/assets/cobranca.svg', '/src/lib/assets/saldos-e-extratos.svg', '/src/lib/assets/fluxo-de-aprovacao.svg', '/src/lib/assets/conta-escrow-azul.svg', '/src/lib/assets/cobranca-em-lote.svg', '/src/lib/assets/gestao-de-usuarios.svg', '/src/lib/assets/check.svg', '/src/lib/assets/lock-icon.svg', // App store badges '/src/lib/assets/apple-store.svg', '/src/lib/assets/google-play.svg', // Logos da empresa '/src/lib/assets/logo-basspago-preta.svg', '/src/lib/assets/icon-slim-basspago.svg' ]; // Recursos para cache dinâmico (não críticos) const dynamicCacheResources = [ '/src/lib/assets/case-1.webp', '/src/lib/assets/case-2.webp', '/src/lib/assets/case-3.webp', '/src/lib/assets/case-4.webp', '/src/lib/assets/case-5.webp', '/src/lib/assets/case-6.webp', '/src/lib/assets/payment-schedule-mockup.svg' ]; // Install event - Cache recursos críticos self.addEventListener('install', (event) => { console.log('[SW] Installing...'); event.waitUntil( caches.open(CACHE_NAME) .then((cache) => { console.log('[SW] Cache opened, adding critical resources...'); // Cache recursos críticos em lotes para evitar timeout const batchSize = 10; const batches = []; for (let i = 0; i < urlsToCache.length; i += batchSize) { batches.push(urlsToCache.slice(i, i + batchSize)); } return batches.reduce((promise, batch) => { return promise.then(() => { console.log('[SW] Caching batch:', batch); return cache.addAll(batch).catch((error) => { console.warn('[SW] Failed to cache batch:', batch, error); // Tenta cachear individualmente em caso de erro return Promise.allSettled( batch.map(url => cache.add(url).catch(e => console.warn('[SW] Failed to cache:', url, e))) ); }); }); }, Promise.resolve()); }) .then(() => { console.log('[SW] Critical resources cached successfully'); }) .catch((error) => { console.error('[SW] Failed to cache critical resources:', error); }) ); // Força a ativação imediata self.skipWaiting(); }); // Activate event - Limpa caches antigos self.addEventListener('activate', (event) => { console.log('[SW] Activating...'); event.waitUntil( caches.keys().then((cacheNames) => { return Promise.all( cacheNames.map((cacheName) => { if (cacheName !== CACHE_NAME) { console.log('[SW] Deleting old cache:', cacheName); return caches.delete(cacheName); } }) ); }).then(() => { console.log('[SW] Old caches cleaned'); // Toma controle de todas as abas abertas return self.clients.claim(); }) ); }); // Fetch event - Estratégia de cache self.addEventListener('fetch', (event) => { const { request } = event; const url = new URL(request.url); // Ignora requests que não são GET if (request.method !== 'GET') { return; } // Ignora requests para outros domínios (exceto fonts) if (url.origin !== location.origin && !url.hostname.includes('fonts')) { return; } event.respondWith( caches.match(request) .then((cachedResponse) => { // Se está no cache, retorna imediatamente if (cachedResponse) { console.log('[SW] Serving from cache:', request.url); // Para recursos críticos, também faz fetch em background para atualizar if (urlsToCache.includes(url.pathname)) { fetch(request).then((response) => { if (response.ok) { caches.open(CACHE_NAME).then((cache) => { cache.put(request, response.clone()); }); } }).catch(() => { // Ignora erros de network em background updates }); } return cachedResponse; } // Se não está no cache, faz fetch console.log('[SW] Fetching from network:', request.url); return fetch(request) .then((response) => { // Só cacheia responses válidos if (!response || response.status !== 200 || response.type !== 'basic') { return response; } // Cacheia recursos dinâmicos se estão na lista if (dynamicCacheResources.includes(url.pathname) || url.pathname.includes('/src/lib/assets/')) { const responseToCache = response.clone(); caches.open(CACHE_NAME) .then((cache) => { console.log('[SW] Caching dynamic resource:', request.url); cache.put(request, responseToCache); }); } return response; }) .catch((error) => { console.error('[SW] Fetch failed:', request.url, error); // Fallback para páginas HTML if (request.headers.get('accept').includes('text/html')) { return caches.match('/'); } throw error; }); }) ); }); // Background Sync para cache de recursos não críticos self.addEventListener('sync', (event) => { if (event.tag === 'background-cache') { event.waitUntil( caches.open(CACHE_NAME) .then((cache) => { console.log('[SW] Background caching dynamic resources...'); return Promise.allSettled( dynamicCacheResources.map(url => cache.add(url).catch(e => console.warn('[SW] Background cache failed:', url, e)) ) ); }) ); } }); // Message event para comunicação com a app self.addEventListener('message', (event) => { if (event.data && event.data.type === 'SKIP_WAITING') { self.skipWaiting(); } if (event.data && event.data.type === 'GET_CACHE_STATUS') { caches.open(CACHE_NAME).then((cache) => { return cache.keys(); }).then((keys) => { event.ports[0].postMessage({ type: 'CACHE_STATUS', cached: keys.length, total: urlsToCache.length }); }); } }); // Periodic background sync (se suportado) self.addEventListener('periodicsync', (event) => { if (event.tag === 'cache-update') { event.waitUntil( caches.open(CACHE_NAME) .then((cache) => { console.log('[SW] Periodic cache update...'); return Promise.allSettled( urlsToCache.map(url => fetch(url).then(response => { if (response.ok) { return cache.put(url, response); } }).catch(e => console.warn('[SW] Periodic update failed:', url, e)) ) ); }) ); } });