Fix animation stale reference
This commit is contained in:
@@ -1,18 +1,83 @@
|
||||
<script setup lang="ts">
|
||||
import { onBeforeUnmount, ref, watch } from 'vue'
|
||||
import { useRegisterSW } from 'virtual:pwa-register/vue'
|
||||
import { useNativeRouter } from '@native-vue-router/core'
|
||||
import { recordPwaUpdateState } from '../pwa'
|
||||
|
||||
const native = useNativeRouter()
|
||||
const { needRefresh, updateServiceWorker } = useRegisterSW()
|
||||
const reloadPending = ref(false)
|
||||
let registration: ServiceWorkerRegistration | undefined
|
||||
let checkTimer: number | undefined
|
||||
let reloading = false
|
||||
let checking = false
|
||||
|
||||
function reloadWhenIdle() {
|
||||
if (!reloadPending.value || native.transaction.value || reloading) return
|
||||
reloading = true
|
||||
window.location.reload()
|
||||
}
|
||||
|
||||
async function checkForUpdate() {
|
||||
if (!registration || checking || document.visibilityState === 'hidden' || !navigator.onLine) return
|
||||
checking = true
|
||||
recordPwaUpdateState('checking', true)
|
||||
try {
|
||||
await registration.update()
|
||||
if (!reloadPending.value) recordPwaUpdateState('current')
|
||||
} catch {
|
||||
recordPwaUpdateState('error')
|
||||
} finally {
|
||||
checking = false
|
||||
}
|
||||
}
|
||||
|
||||
const { needRefresh, updateServiceWorker } = useRegisterSW({
|
||||
immediate: true,
|
||||
onRegisteredSW(_workerUrl, workerRegistration) {
|
||||
registration = workerRegistration
|
||||
void checkForUpdate()
|
||||
if (checkTimer !== undefined) window.clearInterval(checkTimer)
|
||||
checkTimer = window.setInterval(() => void checkForUpdate(), 60_000)
|
||||
},
|
||||
onNeedRefresh() {
|
||||
recordPwaUpdateState('ready')
|
||||
},
|
||||
onNeedReload() {
|
||||
recordPwaUpdateState('ready')
|
||||
reloadPending.value = true
|
||||
reloadWhenIdle()
|
||||
},
|
||||
onRegisterError() {
|
||||
recordPwaUpdateState('error')
|
||||
},
|
||||
})
|
||||
|
||||
function checkWhenActive() {
|
||||
if (document.visibilityState === 'visible') void checkForUpdate()
|
||||
}
|
||||
|
||||
window.addEventListener('focus', checkWhenActive)
|
||||
window.addEventListener('online', checkWhenActive)
|
||||
document.addEventListener('visibilitychange', checkWhenActive)
|
||||
watch(() => native.transaction.value, reloadWhenIdle, { flush: 'post' })
|
||||
|
||||
function update() {
|
||||
reloadPending.value = true
|
||||
if (!native.transaction.value) void updateServiceWorker(true)
|
||||
reloadWhenIdle()
|
||||
}
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
if (checkTimer !== undefined) window.clearInterval(checkTimer)
|
||||
window.removeEventListener('focus', checkWhenActive)
|
||||
window.removeEventListener('online', checkWhenActive)
|
||||
document.removeEventListener('visibilitychange', checkWhenActive)
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<aside v-if="needRefresh" class="update-toast" role="status">
|
||||
<span>A fresh build is ready.</span>
|
||||
<button type="button" :disabled="Boolean(native.transaction.value)" @click="update">Update</button>
|
||||
<aside v-if="needRefresh || reloadPending" class="update-toast" role="status">
|
||||
<span>{{ native.transaction.value ? 'A fresh build will open after this gesture.' : 'A fresh build is ready.' }}</span>
|
||||
<button v-if="needRefresh" type="button" :disabled="Boolean(native.transaction.value)" @click="update">Update</button>
|
||||
</aside>
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user