forked from Mirrors/elk
76 lines
1.8 KiB
TypeScript
76 lines
1.8 KiB
TypeScript
|
export default defineNuxtPlugin((nuxtApp) => {
|
||
|
const router = useRouter()
|
||
|
const route = useRoute()
|
||
|
const track = ref(false)
|
||
|
const { y } = useWindowScroll()
|
||
|
const storage = useLocalStorage<Record<string, number>>('elk-track-scroll', {})
|
||
|
|
||
|
router.beforeEach(async () => {
|
||
|
track.value = false
|
||
|
})
|
||
|
router.onError(async () => {
|
||
|
track.value = true
|
||
|
})
|
||
|
|
||
|
const forceScroll = () => {
|
||
|
storage.value[route.fullPath] = 0
|
||
|
window.scrollTo({ top: 0, left: 0, behavior: 'smooth' })
|
||
|
}
|
||
|
|
||
|
const restoreScroll = () => {
|
||
|
const path = route.fullPath
|
||
|
return nextTick().then(() => {
|
||
|
return new Promise<void>((resolve, reject) => {
|
||
|
setTimeout(() => {
|
||
|
if (path !== route.fullPath) {
|
||
|
reject(new Error('navigation canceled'))
|
||
|
return
|
||
|
}
|
||
|
|
||
|
if (!route.meta || !route.meta?.noScrollTrack) {
|
||
|
const scrollPosition = storage.value[route.fullPath]
|
||
|
if (scrollPosition)
|
||
|
window.scrollTo(0, scrollPosition)
|
||
|
}
|
||
|
else {
|
||
|
forceScroll()
|
||
|
}
|
||
|
|
||
|
resolve()
|
||
|
}, 600)
|
||
|
})
|
||
|
})
|
||
|
}
|
||
|
|
||
|
nuxtApp.hooks.hook('app:suspense:resolve', () => {
|
||
|
if (isHydrated.value) {
|
||
|
restoreScroll().then(() => {
|
||
|
track.value = true
|
||
|
}).catch(noop)
|
||
|
}
|
||
|
})
|
||
|
|
||
|
nuxtApp.hooks.hook('page:finish', () => {
|
||
|
if (isHydrated.value) {
|
||
|
restoreScroll().then(() => {
|
||
|
track.value = true
|
||
|
}).catch(noop)
|
||
|
}
|
||
|
})
|
||
|
|
||
|
watch(() => [track.value, y.value, route], ([trackEnabled, scrollPosition, r]) => {
|
||
|
if (trackEnabled && (!r.meta || !r.meta?.noScrollTrack))
|
||
|
storage.value[r.fullPath] = Math.floor(scrollPosition)
|
||
|
}, { immediate: true, flush: 'pre' })
|
||
|
|
||
|
return {
|
||
|
provide: {
|
||
|
trackScroll: reactive({
|
||
|
forceScroll,
|
||
|
restoreScroll,
|
||
|
track,
|
||
|
}),
|
||
|
},
|
||
|
}
|
||
|
})
|