Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 48 additions & 1 deletion service-worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
const CACHE_VERSION = 'regenx-v7';
const STATIC_CACHE = `${CACHE_VERSION}-static`;
const DYNAMIC_CACHE = `${CACHE_VERSION}-dynamic`;
const MAP_TILE_CACHE = 'leaflet-tiles';
const MAX_TILE_ITEMS = 1500; // ~50MB limit
const SYNC_TAG = 'regenx-order-sync';

const OFFLINE_URL = '/offline.html';
Expand Down Expand Up @@ -103,6 +105,26 @@ async function cacheDynamicResponse(request, response) {
await cache.put(request, response.clone());
}

/**
* Limits the size of a cache by deleting the oldest items.
* @param {string} cacheName - Name of the cache.
* @param {number} maxItems - Maximum number of items allowed.
*/
async function limitCacheSize(cacheName, maxItems) {
try {
const cache = await caches.open(cacheName);
const keys = await cache.keys();
if (keys.length > maxItems) {
const deleteCount = keys.length - maxItems;
for (let i = 0; i < deleteCount; i++) {
await cache.delete(keys[i]);
}
}
} catch (error) {
console.error(`[SW] Failed to limit cache size for ${cacheName}:`, error);
}
}

/**
* Returns the offline fallback page for navigation requests.
* Falls back to a simple HTML response if the cached page is unavailable.
Expand Down Expand Up @@ -144,7 +166,7 @@ self.addEventListener('activate', (event) => {
.then((keys) =>
Promise.all(
keys
.filter((key) => key !== STATIC_CACHE && key !== DYNAMIC_CACHE)
.filter((key) => key !== STATIC_CACHE && key !== DYNAMIC_CACHE && key !== MAP_TILE_CACHE)
.map((key) => {
console.log(`[SW] Deleting stale cache: ${key}`);
return caches.delete(key);
Expand All @@ -163,6 +185,31 @@ self.addEventListener('fetch', (event) => {
return;
}

// Intercept OpenStreetMap tile requests
if (url.hostname.includes('tile.openstreetmap.org')) {
event.respondWith(
caches.open(MAP_TILE_CACHE).then(async (cache) => {
try {
const networkResponse = await fetch(request);
if (networkResponse.ok) {
await cache.put(request, networkResponse.clone());
event.waitUntil(limitCacheSize(MAP_TILE_CACHE, MAX_TILE_ITEMS));
}
return networkResponse;
} catch (error) {
const cachedResponse = await cache.match(request);
if (cachedResponse) {
// Re-put to update insertion order (LRU)
await cache.put(request, cachedResponse.clone());
return cachedResponse;
}
throw error;
}
})
);
return;
}

if (url.origin === location.origin) {
const ignoreSearch = shouldIgnoreSearch(request, url);

Expand Down