@@ -47,6 +47,8 @@ export default function App() {
47
47
const updateToastRef = useRef ( null )
48
48
const [ errorPage , setErrorPage ] = useState < boolean > ( false )
49
49
const isOnline = useOnline ( )
50
+ const refreshing = useRef ( false )
51
+ const [ bgUpdated , setBGUpdated ] = useState ( false )
50
52
const [ validating , setValidating ] = useState ( true )
51
53
const [ approvalToken , setApprovalToken ] = useState < string > ( '' )
52
54
const [ approvalType , setApprovalType ] = useState < APPROVAL_MODAL_TYPE > ( APPROVAL_MODAL_TYPE . CONFIG )
@@ -129,7 +131,22 @@ export default function App() {
129
131
}
130
132
}
131
133
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
+
132
146
useEffect ( ( ) => {
147
+ if ( navigator . serviceWorker ) {
148
+ navigator . serviceWorker . addEventListener ( 'controllerchange' , handleControllerChange )
149
+ }
133
150
// If not K8S_CLIENT then validateToken otherwise directly redirect
134
151
if ( ! window . _env_ . K8S_CLIENT ) {
135
152
// By Passing validations for direct email approval notifications
@@ -142,6 +159,9 @@ export default function App() {
142
159
setValidating ( false )
143
160
defaultRedirection ( )
144
161
}
162
+ return ( ) => {
163
+ navigator . serviceWorker . removeEventListener ( 'controllerchange' , handleControllerChange )
164
+ }
145
165
} , [ ] )
146
166
147
167
const {
@@ -150,9 +170,20 @@ export default function App() {
150
170
} = useRegisterSW ( {
151
171
onRegisteredSW ( swUrl , r ) {
152
172
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 )
156
187
} ,
157
188
onRegisterError ( error ) {
158
189
console . log ( 'SW registration error' , error )
@@ -169,10 +200,11 @@ export default function App() {
169
200
if ( window . isSecureContext && navigator . serviceWorker ) {
170
201
// check for sw updates on page change
171
202
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 )
174
207
}
175
- update ( )
176
208
}
177
209
} , [ location ] )
178
210
@@ -200,6 +232,24 @@ export default function App() {
200
232
}
201
233
} , [ needRefresh ] )
202
234
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
+
203
253
return (
204
254
< Suspense fallback = { null } >
205
255
{ validating ? (
0 commit comments