81 lines
2.0 KiB
TypeScript
81 lines
2.0 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)
|
|
}
|