feat: track scroll position

This commit is contained in:
userquin 2023-02-10 22:13:46 +01:00
parent 0eefcfa281
commit 3270140c3f
14 changed files with 112 additions and 4 deletions

View file

@ -1,4 +1,8 @@
<script setup lang="ts">
definePageMeta({
noScrollTrack: true,
})
const buildInfo = useBuildInfo()
const { t } = useI18n()

View file

@ -1,3 +1,9 @@
<script setup lang="ts">
definePageMeta({
noScrollTrack: true,
})
</script>
<template>
<div min-h-screen flex justify-center items-center>
<div text-center flex="~ col gap-2" items-center>

View file

@ -1,4 +1,8 @@
<script setup lang="ts">
definePageMeta({
noScrollTrack: true,
})
const { t } = useI18n()
useHeadFixed({

View file

@ -1,4 +1,8 @@
<script setup lang="ts">
definePageMeta({
noScrollTrack: true,
})
const { t } = useI18n()
useHeadFixed({

View file

@ -1,6 +1,7 @@
<script setup lang="ts">
definePageMeta({
middleware: 'auth',
noScrollTrack: true,
})
const { t } = useI18n()

View file

@ -1,6 +1,7 @@
<script setup lang="ts">
definePageMeta({
middleware: 'auth',
noScrollTrack: true,
})
const { t } = useI18n()

View file

@ -4,6 +4,7 @@ definePageMeta({
if (!useAppConfig().pwaEnabled)
return navigateTo('/settings/notifications')
}],
noScrollTrack: true,
})
const { t } = useI18n()

View file

@ -1,4 +1,8 @@
<script setup lang="ts">
definePageMeta({
noScrollTrack: true,
})
const { t } = useI18n()
useHeadFixed({

View file

@ -1,12 +1,11 @@
<script lang="ts" setup>
import type { mastodon } from 'masto'
import { ofetch } from 'ofetch'
import { useForm } from 'slimeform'
import { parse } from 'ultrahtml'
import type { Component } from 'vue'
definePageMeta({
middleware: 'auth',
noScrollTrack: true,
})
const { t } = useI18n()

View file

@ -1,6 +1,7 @@
<script setup lang="ts">
definePageMeta({
middleware: 'auth',
noScrollTrack: true,
})
const { t } = useI18n()

View file

@ -1,6 +1,7 @@
<script setup lang="ts">
definePageMeta({
middleware: 'auth',
noScrollTrack: true,
})
const { t } = useI18n()

View file

@ -3,6 +3,10 @@
import { fileOpen } from 'browser-fs-access'
import type { UserLogin } from '~/types'
definePageMeta({
noScrollTrack: true,
})
const { t } = useI18n()
useHeadFixed({

View file

@ -1,8 +1,11 @@
export default defineNuxtPlugin(() => {
export default defineNuxtPlugin((/* nuxtApp */) => {
return {
provide: {
scrollToTop: () => {
window.scrollTo({ top: 0, left: 0, behavior: 'smooth' })
// if (typeof force === 'boolean' && force)
// nuxtApp.$trackScroll.forceScroll()
// window.scrollTo({ top: 0, left: 0, behavior: 'smooth' })
},
},
}

View file

@ -0,0 +1,75 @@
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,
}),
},
}
})