@@ -701,23 +701,28 @@ function StorePage(props: { api: PageApi }): ReactElement {
701701 const [ , bumpCounts ] = React . useReducer ( ( n : number ) => n + 1 , 0 ) ;
702702 const loadedRef = React . useRef ( false ) ;
703703 const loadingRef = React . useRef ( false ) ;
704+ const loadedAtRef = React . useRef ( 0 ) ;
704705 const autoDisabledRevoked = React . useRef ( new Set < string > ( ) ) ;
705706 const resetTimer = React . useRef < ReturnType < typeof setTimeout > | null > ( null ) ;
706707 const importInput = React . useRef < HTMLInputElement > ( null ) ;
707708
708709 const refreshRegistry = ( ) => setRegistryEpoch ( ( n ) => n + 1 ) ;
709710
710- const load = React . useCallback ( async ( ) => {
711+ const load = React . useCallback ( async ( background = false ) => {
711712 // A failed load must retry on the next visit, not latch.
712713 if ( loadingRef . current ) return ;
713714 loadingRef . current = true ;
714- setStatus ( "loading vaults…" ) ;
715+ // A background refresh keeps the current grid on screen instead
716+ // of flashing a loading state over it.
717+ if ( ! background ) setStatus ( "loading vaults…" ) ;
715718 let next : Catalog = { modules : [ ] , revoked : { } , ok : false } ;
716719 try {
717720 next = await loadCatalog ( ) ;
721+ if ( background && ! next . ok ) return ; // keep the last good catalog
718722 // Only a load where some vault answered may latch; an offline
719723 // page keeps retrying on later visits.
720724 loadedRef . current = next . ok ;
725+ if ( next . ok ) loadedAtRef . current = Date . now ( ) ;
721726 setCatalog ( next ) ;
722727 setStatus (
723728 next . ok
@@ -738,12 +743,20 @@ function StorePage(props: { api: PageApi }): ReactElement {
738743 void load ( ) ;
739744 } , [ load ] ) ;
740745
741- // A revisit re-renders from live registry state, or retries the
742- // catalog when no vault has answered yet.
746+ // A revisit re-renders from live registry state, retries the catalog
747+ // when no vault has answered yet, and refreshes a stale catalog in
748+ // the background: modules publish continuously, so a latched catalog
749+ // must not outlive the session (that hid freshly published themes
750+ // until a client restart).
751+ const CATALOG_TTL_MS = 5 * 60 * 1000 ;
743752 React . useEffect ( ( ) => {
744753 props . api . onRevisit = ( ) => {
745- if ( loadedRef . current ) refreshRegistry ( ) ;
746- else void load ( ) ;
754+ if ( ! loadedRef . current ) {
755+ void load ( ) ;
756+ return ;
757+ }
758+ refreshRegistry ( ) ;
759+ if ( Date . now ( ) - loadedAtRef . current > CATALOG_TTL_MS ) void load ( true ) ;
747760 } ;
748761 return ( ) => {
749762 props . api . onRevisit = null ;
0 commit comments