@@ -541,6 +541,7 @@ <h2 id="offline-title">Offline bundle</h2>
541541 const resetBusyLabel = resetButton && resetButton . dataset && resetButton . dataset . busyLabel
542542 ? resetButton . dataset . busyLabel
543543 : 'Refreshing offline bundle…' ;
544+ const METADATA_CACHE_NAME = 'toolbox-offline-metadata' ;
544545
545546 if ( ! statusEl || ! progressWrapper || ! progressBar || ! progressFill || ! progressDetail ) {
546547 return ;
@@ -597,6 +598,23 @@ <h2 id="offline-title">Offline bundle</h2>
597598 return `${ formatter . format ( Number ( value . toFixed ( fractionDigits ) ) ) } ${ units [ unitIndex ] } ` ;
598599 }
599600
601+ async function readCachedManifest ( ) {
602+ try {
603+ const cache = await caches . open ( METADATA_CACHE_NAME ) ;
604+ const requestUrl = new URL ( '__toolbox-offline-manifest__' , self . location . href ) . toString ( ) ;
605+ const response = await cache . match ( requestUrl ) ;
606+ if ( ! response ) {
607+ return null ;
608+ }
609+
610+ const manifest = await response . json ( ) ;
611+ return manifest && typeof manifest === 'object' ? manifest : null ;
612+ } catch ( error ) {
613+ console . warn ( 'Failed to read cached offline manifest' , error ) ;
614+ return null ;
615+ }
616+ }
617+
600618 function getCommitLabel ( commit ) {
601619 if ( ! commit || typeof commit !== 'object' ) {
602620 return '' ;
@@ -837,42 +855,54 @@ <h2 id="offline-title">Offline bundle</h2>
837855 return ;
838856 }
839857
858+ let manifest ;
859+ let manifestSource = 'network' ;
860+
840861 try {
841862 const response = await fetch ( 'offline-manifest.json' , { cache : 'no-store' } ) ;
842863 if ( ! response . ok ) {
843864 throw new Error ( `Manifest request failed with status ${ response . status } ` ) ;
844865 }
845866
846- const manifest = await response . json ( ) ;
847- state . manifest = manifest ;
848- const assets = Array . isArray ( manifest . assets ) ? manifest . assets : [ ] ;
849- const totalBytes = Number . isFinite ( manifest . totalBytes )
850- ? manifest . totalBytes
851- : assets . reduce ( ( total , asset ) => total + ( Number ( asset . bytes ) || 0 ) , 0 ) ;
852-
853- if ( ! Number . isFinite ( manifest . totalBytes ) ) {
854- manifest . totalBytes = totalBytes ;
855- }
856- if ( typeof manifest . totalAssets !== 'number' ) {
857- manifest . totalAssets = assets . length ;
867+ manifest = await response . json ( ) ;
868+ } catch ( error ) {
869+ console . warn ( 'Failed to load offline manifest from network, attempting cached copy.' , error ) ;
870+ manifest = await readCachedManifest ( ) ;
871+ if ( ! manifest ) {
872+ console . error ( 'Unable to load offline manifest from network or cache' , error ) ;
873+ setStatus ( 'Unable to load the offline manifest. Refresh when you are back online.' ) ;
874+ return ;
858875 }
876+ manifestSource = 'cache' ;
877+ }
859878
860- const summary = buildBundleSummary ( {
861- version : manifest . version ,
862- totalAssets : assets . length ,
863- totalBytes,
864- commit : manifest . commit || null
865- } ) ;
879+ const assets = Array . isArray ( manifest . assets ) ? manifest . assets : [ ] ;
880+ const totalBytes = Number . isFinite ( manifest . totalBytes )
881+ ? manifest . totalBytes
882+ : assets . reduce ( ( total , asset ) => total + ( Number ( asset . bytes ) || 0 ) , 0 ) ;
866883
867- updateMeta ( summary ) ;
868- setStatus ( 'Offline bundle ready to download.' ) ;
869- updateResetAvailability ( ) ;
870- } catch ( error ) {
871- console . error ( 'Failed to load offline manifest' , error ) ;
872- setStatus ( 'Unable to load the offline manifest. Refresh when you are back online.' ) ;
873- return ;
884+ if ( ! Number . isFinite ( manifest . totalBytes ) ) {
885+ manifest . totalBytes = totalBytes ;
886+ }
887+ if ( typeof manifest . totalAssets !== 'number' ) {
888+ manifest . totalAssets = assets . length ;
874889 }
875890
891+ state . manifest = manifest ;
892+
893+ const summary = buildBundleSummary ( {
894+ version : manifest . version ,
895+ totalAssets : assets . length ,
896+ totalBytes,
897+ commit : manifest . commit || null
898+ } ) ;
899+
900+ updateMeta ( summary ) ;
901+ setStatus ( manifestSource === 'cache' ? 'Offline bundle ready for offline use.' : 'Offline bundle ready to download.' ) ;
902+ updateResetAvailability ( ) ;
903+
904+ const shouldRequestCaching = manifestSource === 'network' ;
905+
876906 try {
877907 const registration = await navigator . serviceWorker . register ( 'service-worker.js' ) ;
878908 navigator . serviceWorker . addEventListener ( 'message' , handleMessage ) ;
@@ -886,7 +916,9 @@ <h2 id="offline-title">Offline bundle</h2>
886916 const readyRegistration = await navigator . serviceWorker . ready ;
887917 state . registration = readyRegistration ;
888918 updateResetAvailability ( ) ;
889- requestCaching ( readyRegistration ) ;
919+ if ( shouldRequestCaching ) {
920+ requestCaching ( readyRegistration ) ;
921+ }
890922 } catch ( error ) {
891923 console . error ( 'Service worker registration failed' , error ) ;
892924 setStatus ( 'Unable to register the offline service worker.' ) ;
0 commit comments