@@ -47,6 +47,8 @@ export default function App() {
4747 const updateToastRef = useRef ( null )
4848 const [ errorPage , setErrorPage ] = useState < boolean > ( false )
4949 const isOnline = useOnline ( )
50+ const refreshing = useRef ( false )
51+ const [ bgUpdated , setBGUpdated ] = useState ( false )
5052 const [ validating , setValidating ] = useState ( true )
5153 const [ approvalToken , setApprovalToken ] = useState < string > ( '' )
5254 const [ approvalType , setApprovalType ] = useState < APPROVAL_MODAL_TYPE > ( APPROVAL_MODAL_TYPE . CONFIG )
@@ -129,7 +131,22 @@ export default function App() {
129131 }
130132 }
131133
134+ function handleControllerChange ( ) {
135+ if ( refreshing . current ) {
136+ return
137+ }
138+ if ( document . visibilityState === 'visible' ) {
139+ window . location . reload ( )
140+ refreshing . current = true
141+ } else {
142+ setBGUpdated ( true )
143+ }
144+ }
145+
132146 useEffect ( ( ) => {
147+ if ( navigator . serviceWorker ) {
148+ navigator . serviceWorker . addEventListener ( 'controllerchange' , handleControllerChange )
149+ }
133150 // If not K8S_CLIENT then validateToken otherwise directly redirect
134151 if ( ! window . _env_ . K8S_CLIENT ) {
135152 // By Passing validations for direct email approval notifications
@@ -142,6 +159,9 @@ export default function App() {
142159 setValidating ( false )
143160 defaultRedirection ( )
144161 }
162+ return ( ) => {
163+ navigator . serviceWorker . removeEventListener ( 'controllerchange' , handleControllerChange )
164+ }
145165 } , [ ] )
146166
147167 const {
@@ -150,9 +170,20 @@ export default function App() {
150170 } = useRegisterSW ( {
151171 onRegisteredSW ( swUrl , r ) {
152172 console . log ( `Service Worker at: ${ swUrl } ` )
153- if ( r ) {
154- r . update ( )
155- }
173+ r &&
174+ setInterval ( async ( ) => {
175+ if ( ! ( ! r . installing && navigator ) ) return
176+ if ( 'connection' in navigator && ! navigator . onLine ) return
177+ const resp = await fetch ( swUrl , {
178+ cache : 'no-store' ,
179+ headers : {
180+ cache : 'no-store' ,
181+ 'cache-control' : 'no-cache' ,
182+ } ,
183+ } )
184+
185+ if ( resp ?. status === 200 ) await r . update ( )
186+ } , 1000 * 60 )
156187 } ,
157188 onRegisterError ( error ) {
158189 console . log ( 'SW registration error' , error )
@@ -169,10 +200,11 @@ export default function App() {
169200 if ( window . isSecureContext && navigator . serviceWorker ) {
170201 // check for sw updates on page change
171202 navigator . serviceWorker . getRegistrations ( ) . then ( ( regs ) => regs . forEach ( ( reg ) => reg . update ( ) ) )
172- if ( ! needRefresh ) {
173- return
203+ if ( needRefresh ) {
204+ update ( )
205+ } else if ( toast . isActive ( updateToastRef . current ) ) {
206+ toast . dismiss ( updateToastRef . current )
174207 }
175- update ( )
176208 }
177209 } , [ location ] )
178210
@@ -200,6 +232,24 @@ export default function App() {
200232 }
201233 } , [ needRefresh ] )
202234
235+ useEffect ( ( ) => {
236+ if ( ! bgUpdated ) {
237+ return
238+ }
239+ const bgUpdatedToastBody = (
240+ < UpdateToast
241+ onClick = { ( ) => window . location . reload ( ) }
242+ text = "This page has been updated. Please save any unsaved changes and refresh."
243+ buttonText = "Reload"
244+ />
245+ )
246+ if ( toast . isActive ( updateToastRef . current ) ) {
247+ toast . update ( updateToastRef . current , { render : bgUpdatedToastBody } )
248+ } else {
249+ updateToastRef . current = toast . info ( bgUpdatedToastBody , { autoClose : false , closeButton : false } )
250+ }
251+ } , [ bgUpdated ] )
252+
203253 return (
204254 < Suspense fallback = { null } >
205255 { validating ? (
0 commit comments