Some checks failed
Build and deploy updated apps / Build & deploy (push) Failing after 50s
57 lines
1.5 KiB
TypeScript
57 lines
1.5 KiB
TypeScript
import { isNavigationFailure } from 'vue-router'
|
|
|
|
async function waitFor<T>(
|
|
obtain: () => T | Promise<T>,
|
|
tries = 30,
|
|
delay = 100
|
|
): Promise<T | undefined> {
|
|
for (let i = 0; i < tries; i++) {
|
|
const result = await obtain()
|
|
|
|
if (result !== undefined) {
|
|
return result
|
|
}
|
|
|
|
await new Promise((resolve) => setTimeout(resolve, delay))
|
|
}
|
|
|
|
return undefined
|
|
}
|
|
|
|
export default defineNuxtPlugin((app) => {
|
|
app.hook('app:mounted', () => {
|
|
const router = useRouter()
|
|
|
|
router.options.scrollBehavior = (to, from, savedPosition) => {
|
|
if (to.query.freeze) {
|
|
return false
|
|
}
|
|
|
|
if (to.hash && to.path === from.path) {
|
|
return false
|
|
}
|
|
|
|
return { top: 0 }
|
|
}
|
|
|
|
router.afterEach(async (to, from, failure) => {
|
|
if (isNavigationFailure(failure)) {
|
|
console.warn(`Failed navigation: ${JSON.stringify(failure)}`)
|
|
} else if (to.hash) {
|
|
const [header, element, atTop] = await Promise.all([
|
|
waitFor(() => document.querySelector('#scaffold-header') ?? undefined),
|
|
waitFor(() => document.querySelector(to.hash) ?? undefined),
|
|
waitFor(() => (to.path === from.path || window.scrollY < 10 ? true : undefined)),
|
|
])
|
|
|
|
if (element && atTop) {
|
|
const offset = header ? header.offsetHeight : 0
|
|
const position = element.getBoundingClientRect().top
|
|
|
|
window.scrollTo({ top: position - offset + window.scrollY })
|
|
}
|
|
}
|
|
})
|
|
})
|
|
})
|