@@ -37,6 +37,33 @@ function enforceHoloplayRenderer(config) {
3737 */
3838let appVersion = "unknown" ;
3939
40+ /** Matches `const VER` in `service-worker.js` (read at runtime so CI-stamped deploys stay accurate). */
41+ let serviceWorkerVerStamp = "local" ;
42+
43+ /**
44+ * Same scope key algorithm as `service-worker.js` (BASE_PATH → SCOPE_KEY).
45+ * Uses the registered script URL so subpaths (e.g. GitHub Pages project sites) match the SW.
46+ * @returns {string }
47+ */
48+ function getPwaCacheScopeKey ( ) {
49+ const swPath = new URL ( "service-worker.js" , location . href ) . pathname ;
50+ const basePath = swPath . replace ( / s e r v i c e - w o r k e r \. j s $ / , "" ) ;
51+ return basePath . replace ( / ^ \/ | \/ $ / g, "" ) . replace ( / \/ / g, "-" ) || "root" ;
52+ }
53+
54+ /**
55+ * Offline cache bucket name the service worker uses after a successful install
56+ * (`CACHE_NAME` in `service-worker.js`). If VERSION could not be read, the SW falls back to `v1`.
57+ * @param {string } versionTrimmed
58+ * @param {string } verStamp
59+ * @returns {string }
60+ */
61+ function getExpectedPwaCacheName ( versionTrimmed , verStamp ) {
62+ const prefix = `matrix-sw-${ getPwaCacheScopeKey ( ) } -` ;
63+ const versionSeg = versionTrimmed && versionTrimmed !== "unknown" ? versionTrimmed : "1" ;
64+ return `${ prefix } v${ versionSeg } -${ verStamp } ` ;
65+ }
66+
4067/**
4168 * Load application version from VERSION file
4269 * @returns {Promise<string> } The version string (e.g., "1.0.0")
@@ -53,15 +80,33 @@ async function loadVersion() {
5380 }
5481}
5582
83+ /**
84+ * Read `VER` from the deployed service worker script (same source CI rewrites on gh-pages).
85+ * @returns {Promise<void> }
86+ */
87+ async function loadServiceWorkerVerStamp ( ) {
88+ try {
89+ const url = new URL ( "service-worker.js" , location . href ) . href ;
90+ const response = await fetch ( url , { cache : "no-cache" } ) ;
91+ const text = await response . text ( ) ;
92+ const match = text . match ( / c o n s t \s + V E R \s * = \s * " ( [ ^ " ] * ) " / ) ;
93+ if ( match ) {
94+ serviceWorkerVerStamp = match [ 1 ] ;
95+ }
96+ } catch ( error ) {
97+ console . warn ( "[Matrix] Could not read service worker VER for cache name hint:" , error ) ;
98+ }
99+ }
100+
56101/**
57102 * Display version information to console
58103 * Includes Matrix-themed messaging and helpful cache information
59104 */
60105function displayVersionInfo ( ) {
61- const cacheName = `matrix-v ${ appVersion } ` ;
106+ const cacheName = getExpectedPwaCacheName ( appVersion , serviceWorkerVerStamp ) ;
62107 console . log ( "%c⎡ MATRIX DIGITAL RAIN ⎦" , "color: #0F0; font-size: 16px; font-weight: bold; text-shadow: 0 0 10px #0F0" ) ;
63108 console . log ( `%cVersion: ${ appVersion } ` , "color: #0F0; font-size: 12px" ) ;
64- console . log ( `%cCache : ${ cacheName } ` , "color: #0F0; font-size: 12px" ) ;
109+ console . log ( `%cPWA offline cache : ${ cacheName } ` , "color: #0F0; font-size: 12px" ) ;
65110 console . log ( `%c"Wake up, Neo... The Matrix has you."` , "color: #0F0; font-style: italic; font-size: 10px" ) ;
66111 console . log ( "" ) ;
67112 console . log ( "%cPWA Cache Debug Commands:" , "color: #0F0; font-size: 11px; font-weight: bold" ) ;
@@ -216,7 +261,7 @@ document.body.onload = async () => {
216261 * Load and Display Version Information
217262 * Shows version and cache debugging info in console for PWA management
218263 */
219- await loadVersion ( ) ;
264+ await Promise . all ( [ loadVersion ( ) , loadServiceWorkerVerStamp ( ) ] ) ;
220265 displayVersionInfo ( ) ;
221266
222267 /*
@@ -292,7 +337,7 @@ document.body.onload = async () => {
292337 urlParams . set ( "suppressWarnings" , true ) ;
293338 history . replaceState ( { } , "" , "?" + unescape ( urlParams . toString ( ) ) ) ;
294339 currentMatrixRenderer = await solution ;
295- startMatrix ( currentMatrixRenderer , canvas , matrixConfig ) ;
340+ await startMatrix ( currentMatrixRenderer , canvas , matrixConfig ) ;
296341 canvas . style . display = "unset" ;
297342 document . body . removeChild ( notice ) ;
298343 } ) ;
@@ -303,7 +348,7 @@ document.body.onload = async () => {
303348 * Initialize the chosen rendering solution immediately.
304349 */
305350 currentMatrixRenderer = await solution ;
306- startMatrix ( currentMatrixRenderer , canvas , matrixConfig ) ;
351+ await startMatrix ( currentMatrixRenderer , canvas , matrixConfig ) ;
307352 }
308353} ;
309354
@@ -598,11 +643,11 @@ function setupSpotifyEventListeners() {
598643/**
599644 * Start the Matrix renderer
600645 */
601- function startMatrix ( matrixRenderer , canvas , config ) {
646+ async function startMatrix ( matrixRenderer , canvas , config ) {
602647 // Start the Matrix renderer
603648 // Note: setupFullscreenToggle is called within the renderer implementations
604649 // (webgl/main.js and webgpu/main.js) to avoid duplicate event listeners
605- matrixRenderer . default ( canvas , config ) ;
650+ await matrixRenderer . default ( canvas , config ) ;
606651}
607652
608653/**
@@ -632,7 +677,7 @@ async function initializeGalleryMode() {
632677 const useWebGPU = ( await supportsWebGPU ( ) ) && newConfig . renderer ?. toLowerCase ( ) === "webgpu" ;
633678 const solution = await import ( `./${ useWebGPU ? "webgpu" : "webgl" } /main.js` ) ;
634679 currentMatrixRenderer = solution ;
635- startMatrix ( currentMatrixRenderer , canvas , newConfig ) ;
680+ await startMatrix ( currentMatrixRenderer , canvas , newConfig ) ;
636681 } else {
637682 await restartMatrixWithNewConfig ( newConfig ) ;
638683 }
0 commit comments