Cette page n'est pas encore disponible hors ligne.
Tu peux continuer a naviguer sur les pages deja consultees. Cette route sera disponible hors ligne apres une visite en ligne.
// StripStream Service Worker - Version 2 // Architecture: static + image caching, resilient offline navigation fallback const VERSION = "v2.16"; const STATIC_CACHE = `stripstream-static-${VERSION}`; const PAGES_CACHE = `stripstream-pages-${VERSION}`; // Navigation documents + RSC payloads const API_CACHE = `stripstream-api-${VERSION}`; const IMAGES_CACHE = `stripstream-images-${VERSION}`; const BOOKS_CACHE = "stripstream-books"; // Never version this - managed by DownloadManager const OFFLINE_PAGE = "/offline.html"; const OPTIONAL_PRECACHE_ASSETS = ["/manifest.json"]; // Cache size limits const IMAGES_CACHE_MAX_ENTRIES = 500; // ============================================================================ // Utility Functions - Request Detection // ============================================================================ function isNextStaticResource(url) { return url.includes("/_next/static/"); } function isNextRSCRequest(request) { const url = new URL(request.url); return url.searchParams.has("_rsc") || request.headers.get("RSC") === "1"; } function isImageRequest(url) { return url.includes("/api/komga/images/"); } function isBookPageRequest(url) { // Book pages: /api/komga/images/books/{id}/pages/{num} or /api/komga/books/{id}/pages/{num} // These are handled by manual download (DownloadManager) - don't cache via SWR return ( (url.includes("/api/komga/images/books/") || url.includes("/api/komga/books/")) && url.includes("/pages/") ); } function shouldCacheResponse(response, options = {}) { if (!response || !response.ok) return false; if (options.allowPrivateNoStore) { return true; } const cacheControl = response.headers.get("Cache-Control") || ""; return !/no-store|private/i.test(cacheControl); } async function getOfflineFallbackResponse() { // Prefer dedicated offline page to avoid route mismatches const staticCache = await caches.open(STATIC_CACHE); const offlinePage = await staticCache.match(OFFLINE_PAGE); if (offlinePage) { return offlinePage; } // If offline page is unavailable, fallback to root app shell const pagesCache = await caches.open(PAGES_CACHE); const rootPage = await pagesCache.match("/"); if (rootPage && isHtmlResponse(rootPage)) { return rootPage; } // Fallback to any cached HTML app shell page before static offline page const keys = await pagesCache.keys(); const pageKey = [...keys].reverse().find((request) => { const key = getVisitablePageKey(request.url); return key !== null; }); if (pageKey) { const appShellPage = await pagesCache.match(pageKey); if (appShellPage && isHtmlResponse(appShellPage)) { return appShellPage; } } return createInlineOfflineResponse(); } function getVisitablePageKey(rawUrl) { try { const url = new URL(rawUrl); if (url.origin !== self.location.origin) { return null; } if (url.pathname.startsWith("/api/") || url.pathname.startsWith("/_next/")) { return null; } url.searchParams.delete("_rsc"); url.searchParams.delete("__sw_rsc"); const search = url.searchParams.toString(); return `${url.pathname}${search ? `?${search}` : ""}`; } catch { return null; } } function isHtmlResponse(response) { if (!response) return false; const contentType = response.headers.get("content-type") || ""; return contentType.includes("text/html"); } function createInlineOfflineResponse() { return new Response( `

Tu peux continuer a naviguer sur les pages deja consultees. Cette route sera disponible hors ligne apres une visite en ligne.