6 changed files with 34 additions and 125 deletions
@ -1,21 +0,0 @@ |
|||||||
{ |
|
||||||
"name": "Decent Newsroom", |
|
||||||
"short_name": "Newsroom", |
|
||||||
"icons": [ |
|
||||||
{ |
|
||||||
"src": "/icons/web-app-manifest-192x192.png", |
|
||||||
"sizes": "192x192", |
|
||||||
"type": "image/png", |
|
||||||
"purpose": "maskable" |
|
||||||
}, |
|
||||||
{ |
|
||||||
"src": "/icons/web-app-manifest-512x512.png", |
|
||||||
"sizes": "512x512", |
|
||||||
"type": "image/png", |
|
||||||
"purpose": "maskable" |
|
||||||
} |
|
||||||
], |
|
||||||
"theme_color": "#ffffff", |
|
||||||
"background_color": "#ffffff", |
|
||||||
"display": "standalone" |
|
||||||
} |
|
||||||
@ -1,11 +0,0 @@ |
|||||||
<!DOCTYPE html> |
|
||||||
<html lang="en"> |
|
||||||
<head> |
|
||||||
<meta charset="UTF-8" /> |
|
||||||
<title>Decent Newsroom is offline</title> |
|
||||||
</head> |
|
||||||
<body> |
|
||||||
<h1>You are offline</h1> |
|
||||||
<p>Please reconnect to use the app.</p> |
|
||||||
</body> |
|
||||||
</html> |
|
||||||
@ -1,89 +1,11 @@ |
|||||||
const CACHE_NAME = 'newsroom-pwa-v0.0.1'; |
self.addEventListener('install', async (event) => { |
||||||
const URLS_TO_CACHE = [ |
// Activate the service worker immediately after install
|
||||||
'/offline.html' |
await self.skipWaiting(); |
||||||
]; |
|
||||||
|
|
||||||
// Install: cache initial assets
|
|
||||||
self.addEventListener('install', (event) => { |
|
||||||
event.waitUntil( |
|
||||||
caches.open(CACHE_NAME).then(async (cache) => { |
|
||||||
const urls = URLS_TO_CACHE.map(async (url) => { |
|
||||||
try { |
|
||||||
const response = await fetch(url); |
|
||||||
if (response.ok && response.type === 'basic') { |
|
||||||
await cache.put(url, response.clone()); |
|
||||||
} else { |
|
||||||
console.warn(`[SW] Skipped caching ${url}: invalid response`); |
|
||||||
} |
|
||||||
} catch (err) { |
|
||||||
console.warn(`[SW] Failed to fetch ${url}:`, err); |
|
||||||
} |
|
||||||
}); |
|
||||||
|
|
||||||
await Promise.all(urls); |
|
||||||
}) |
|
||||||
); |
|
||||||
self.skipWaiting(); |
|
||||||
}); |
}); |
||||||
|
|
||||||
// Activate: clean up old caches
|
|
||||||
self.addEventListener('activate', (event) => { |
self.addEventListener('activate', (event) => { |
||||||
event.waitUntil( |
// Take control of all clients immediately
|
||||||
caches.keys().then((cacheNames) => |
event.waitUntil(self.clients.claim()); |
||||||
Promise.all( |
|
||||||
cacheNames |
|
||||||
.filter((name) => name !== CACHE_NAME) |
|
||||||
.map((name) => caches.delete(name)) |
|
||||||
) |
|
||||||
) |
|
||||||
); |
|
||||||
self.clients.claim(); |
|
||||||
}); |
}); |
||||||
|
|
||||||
// Fetch: serve from cache, fallback to network, then offline
|
// No fetch or cache handlers — fully fall-through
|
||||||
self.addEventListener('fetch', (event) => { |
|
||||||
const request = event.request; |
|
||||||
|
|
||||||
// Only handle HTTP GET requests
|
|
||||||
if ( |
|
||||||
request.method !== 'GET' || |
|
||||||
!request.url.startsWith('http') |
|
||||||
) { |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
// Skip cache for dynamic routes
|
|
||||||
const isDynamic = request.url.includes('/cat/') ; |
|
||||||
// Exclude dynamic paths
|
|
||||||
const isExcluded = |
|
||||||
request.url.startsWith('/login') || |
|
||||||
request.url.startsWith('/logout') || |
|
||||||
request.url.startsWith('/_components/'); |
|
||||||
|
|
||||||
if (isDynamic || isExcluded) { |
|
||||||
return; // Don't intercept
|
|
||||||
} |
|
||||||
|
|
||||||
event.respondWith( |
|
||||||
caches.match(request).then((cached) => { |
|
||||||
if (cached) return cached; |
|
||||||
|
|
||||||
return fetch(request) |
|
||||||
.then((response) => { |
|
||||||
// Optionally cache fetched responses
|
|
||||||
if ( |
|
||||||
response && |
|
||||||
response.status === 200 && |
|
||||||
response.type === 'basic' |
|
||||||
) { |
|
||||||
const responseClone = response.clone(); |
|
||||||
caches.open(CACHE_NAME).then((cache) => |
|
||||||
cache.put(request, responseClone) |
|
||||||
); |
|
||||||
} |
|
||||||
return response; |
|
||||||
}) |
|
||||||
.catch(() => caches.match('/offline.html')); |
|
||||||
}) |
|
||||||
); |
|
||||||
}); |
|
||||||
|
|||||||
@ -0,0 +1,20 @@ |
|||||||
|
{ |
||||||
|
"name": "Decent Newsroom", |
||||||
|
"short_name": "Newsroom", |
||||||
|
"start_url": "/?source=pwa", |
||||||
|
"icons": [ |
||||||
|
{ |
||||||
|
"src": "{{ asset('icons/web-app-manifest-192x192.png') }}", |
||||||
|
"sizes": "192x192", |
||||||
|
"type": "image/png" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"src": "{{ asset('icons/web-app-manifest-512x512.png') }}", |
||||||
|
"sizes": "512x512", |
||||||
|
"type": "image/png" |
||||||
|
} |
||||||
|
], |
||||||
|
"theme_color": "#ffffff", |
||||||
|
"background_color": "#ffffff", |
||||||
|
"display": "standalone" |
||||||
|
} |
||||||
Loading…
Reference in new issue