78 lines
2.1 KiB
TypeScript
78 lines
2.1 KiB
TypeScript
import './PWABadge.css'
|
|
|
|
import { useRegisterSW } from 'virtual:pwa-register/react'
|
|
|
|
function PWABadge() {
|
|
// check for updates every hour
|
|
const period = 60 * 60 * 1000
|
|
|
|
const {
|
|
offlineReady: [offlineReady, setOfflineReady],
|
|
needRefresh: [needRefresh, setNeedRefresh],
|
|
updateServiceWorker,
|
|
} = useRegisterSW({
|
|
onRegisteredSW(swUrl, r) {
|
|
if (period <= 0) return
|
|
if (r?.active?.state === 'activated') {
|
|
registerPeriodicSync(period, swUrl, r)
|
|
}
|
|
else if (r?.installing) {
|
|
r.installing.addEventListener('statechange', (e) => {
|
|
const sw = e.target as ServiceWorker
|
|
if (sw.state === 'activated')
|
|
registerPeriodicSync(period, swUrl, r)
|
|
})
|
|
}
|
|
},
|
|
})
|
|
|
|
function close() {
|
|
setOfflineReady(false)
|
|
setNeedRefresh(false)
|
|
}
|
|
|
|
return (
|
|
<div className="PWABadge" role="alert" aria-labelledby="toast-message">
|
|
{ (offlineReady || needRefresh)
|
|
&& (
|
|
<div className="PWABadge-toast">
|
|
<div className="PWABadge-message">
|
|
{ offlineReady
|
|
? <span id="toast-message">App ready to work offline</span>
|
|
: <span id="toast-message">New content available, click on reload button to update.</span>}
|
|
</div>
|
|
<div className="PWABadge-buttons">
|
|
{ needRefresh && <button className="PWABadge-toast-button" onClick={() => updateServiceWorker(true)}>Reload</button> }
|
|
<button className="PWABadge-toast-button" onClick={() => close()}>Close</button>
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export default PWABadge
|
|
|
|
/**
|
|
* This function will register a periodic sync check every hour, you can modify the interval as needed.
|
|
*/
|
|
function registerPeriodicSync(period: number, swUrl: string, r: ServiceWorkerRegistration) {
|
|
if (period <= 0) return
|
|
|
|
setInterval(async () => {
|
|
if ('onLine' in navigator && !navigator.onLine)
|
|
return
|
|
|
|
const resp = await fetch(swUrl, {
|
|
cache: 'no-store',
|
|
headers: {
|
|
'cache': 'no-store',
|
|
'cache-control': 'no-cache',
|
|
},
|
|
})
|
|
|
|
if (resp?.status === 200)
|
|
await r.update()
|
|
}, period)
|
|
}
|