From e72fd1ac16c273b8bf74ecd65f9220ce689d1c3b Mon Sep 17 00:00:00 2001 From: AlejandroAkbal <37181533+AlejandroAkbal@users.noreply.github.com> Date: Fri, 13 Mar 2026 10:13:32 -0700 Subject: [PATCH] fix: remeasure virtualized rows after scroll restore --- pages/posts/[domain].vue | 56 ++++++++++++++++++++++++-- pages/premium/saved-posts/[domain].vue | 56 ++++++++++++++++++++++++-- 2 files changed, 106 insertions(+), 6 deletions(-) diff --git a/pages/posts/[domain].vue b/pages/posts/[domain].vue index d2182468..6a6c9aac 100644 --- a/pages/posts/[domain].vue +++ b/pages/posts/[domain].vue @@ -572,10 +572,16 @@ const parentRef = ref(null) const parentOffsetRef = ref(0) + let scrollRestoreRemeasureTimeout: ReturnType | null = null - onMounted(() => { - parentOffsetRef.value = parentRef.value?.offsetTop ?? 0 - }) + function clearScrollRestoreRemeasureTimeout() { + if (scrollRestoreRemeasureTimeout == null) { + return + } + + clearTimeout(scrollRestoreRemeasureTimeout) + scrollRestoreRemeasureTimeout = null + } const rowVirtualizerOptions = computed(() => { return { @@ -647,6 +653,50 @@ }) } + function remeasureAfterScrollRestore() { + if (!import.meta.client || window.scrollY === 0) { + return + } + + clearScrollRestoreRemeasureTimeout() + + nextTick(() => { + rowVirtualizer.value.measure() + + requestAnimationFrame(() => { + rowVirtualizer.value.measure() + + scrollRestoreRemeasureTimeout = setTimeout(() => { + rowVirtualizer.value.measure() + scrollRestoreRemeasureTimeout = null + }, 250) + }) + }) + } + + function onPageShow() { + remeasureAfterScrollRestore() + } + + onMounted(() => { + parentOffsetRef.value = parentRef.value?.offsetTop ?? 0 + + remeasureAfterScrollRestore() + window.addEventListener('pageshow', onPageShow) + }) + + onBeforeUnmount(() => { + clearScrollRestoreRemeasureTimeout() + window.removeEventListener('pageshow', onPageShow) + }) + + watch( + () => allRows.value.length, + () => { + remeasureAfterScrollRestore() + } + ) + /** * SEO */ diff --git a/pages/premium/saved-posts/[domain].vue b/pages/premium/saved-posts/[domain].vue index 3bbcad14..de24a7f3 100644 --- a/pages/premium/saved-posts/[domain].vue +++ b/pages/premium/saved-posts/[domain].vue @@ -474,10 +474,16 @@ const parentRef = ref(null) const parentOffsetRef = ref(0) + let scrollRestoreRemeasureTimeout: ReturnType | null = null - onMounted(() => { - parentOffsetRef.value = parentRef.value?.offsetTop ?? 0 - }) + function clearScrollRestoreRemeasureTimeout() { + if (scrollRestoreRemeasureTimeout == null) { + return + } + + clearTimeout(scrollRestoreRemeasureTimeout) + scrollRestoreRemeasureTimeout = null + } const rowVirtualizerOptions = computed(() => { return { @@ -549,6 +555,50 @@ }) } + function remeasureAfterScrollRestore() { + if (!import.meta.client || window.scrollY === 0) { + return + } + + clearScrollRestoreRemeasureTimeout() + + nextTick(() => { + rowVirtualizer.value.measure() + + requestAnimationFrame(() => { + rowVirtualizer.value.measure() + + scrollRestoreRemeasureTimeout = setTimeout(() => { + rowVirtualizer.value.measure() + scrollRestoreRemeasureTimeout = null + }, 250) + }) + }) + } + + function onPageShow() { + remeasureAfterScrollRestore() + } + + onMounted(() => { + parentOffsetRef.value = parentRef.value?.offsetTop ?? 0 + + remeasureAfterScrollRestore() + window.addEventListener('pageshow', onPageShow) + }) + + onBeforeUnmount(() => { + clearScrollRestoreRemeasureTimeout() + window.removeEventListener('pageshow', onPageShow) + }) + + watch( + () => allRows.value.length, + () => { + remeasureAfterScrollRestore() + } + ) + /** * SEO */