fix autoscroll
This commit is contained in:
@@ -200,13 +200,9 @@ function setupIntersectionObserver() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function handleIntersection(entries, topbarHeight = 0) {
|
function handleIntersection(entries, topbarHeight = 0) {
|
||||||
// An article that has scrolled past the (possibly sticky-bar-shrunk) top
|
// Resolve all affected feeds before touching feeds.value — the target.id
|
||||||
// edge of the viewport (not intersecting, bounding box above that edge)
|
// indices are render-time positions that shift once we splice the array.
|
||||||
// has been read. Resolve all affected feeds up front, before any removal —
|
|
||||||
// splicing `feeds` while iterating would shift the array indices that later
|
|
||||||
// entries' `target.id` refer to, causing the wrong item to be marked read
|
|
||||||
// and removed.
|
|
||||||
const readFeeds = entries
|
const readFeeds = entries
|
||||||
.filter(entry => initialLoad === true && !entry.isIntersecting && entry.boundingClientRect.y < topbarHeight)
|
.filter(entry => initialLoad === true && !entry.isIntersecting && entry.boundingClientRect.y < topbarHeight)
|
||||||
.map(entry => feeds.value[entry.target.id])
|
.map(entry => feeds.value[entry.target.id])
|
||||||
@@ -214,22 +210,38 @@ async function handleIntersection(entries, topbarHeight = 0) {
|
|||||||
|
|
||||||
if (readFeeds.length === 0) return
|
if (readFeeds.length === 0) return
|
||||||
|
|
||||||
for (const feed of readFeeds) {
|
// Disconnect before the DOM mutation. In card layout the cards are short
|
||||||
await markRead(feed.id)
|
// enough that the shift caused by removing one can push the next card above
|
||||||
|
// the header, which the observer would immediately treat as another read —
|
||||||
|
// cascading until many articles disappear at once.
|
||||||
|
if (observer) {
|
||||||
|
observer.disconnect()
|
||||||
|
observer = null
|
||||||
}
|
}
|
||||||
|
|
||||||
const readIds = new Set(readFeeds.map(feed => feed.id))
|
const readIds = new Set(readFeeds.map(feed => feed.id))
|
||||||
feeds.value = feeds.value.filter(feed => !readIds.has(feed.id))
|
feeds.value = feeds.value.filter(feed => !readIds.has(feed.id))
|
||||||
// Removing .observe nodes that have already scrolled above the viewport
|
|
||||||
// shrinks the document above the current scroll position — native CSS
|
for (const feed of readFeeds) {
|
||||||
// scroll anchoring (on by default, no overflow-anchor override here)
|
markRead(feed.id)
|
||||||
// compensates for that automatically by keeping the visually-anchored
|
}
|
||||||
// node in place. Do NOT add a scrollIntoView()/scrollTo() here: an
|
|
||||||
// earlier version called `document.getElementById(0)?.scrollIntoView()`
|
nextTick().then(() => {
|
||||||
// to fix a past scroll-jump complaint, but by the time several articles
|
// If scroll anchoring didn't compensate for the removed content (common
|
||||||
// have been read, id "0" is an already-read element far above the
|
// with position:fixed headers and overflow-x:hidden on body), the first
|
||||||
// viewport — forcing a jump to it fights scroll anchoring and is exactly
|
// remaining article will have drifted above the header. Correct the scroll
|
||||||
// the stutter being fixed now.
|
// position so it sits exactly at the header bottom before reconnecting —
|
||||||
|
// otherwise the initial observation would immediately mark everything above
|
||||||
|
// the topbar as read and cascade until the list is empty.
|
||||||
|
const first = document.querySelector('.observe')
|
||||||
|
if (first) {
|
||||||
|
const top = first.getBoundingClientRect().top
|
||||||
|
if (top < topbarHeight) {
|
||||||
|
window.scrollBy(0, top - topbarHeight)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setupIntersectionObserver()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function setInitialLoad(value) {
|
function setInitialLoad(value) {
|
||||||
@@ -295,6 +307,7 @@ async function toggleLayout() {
|
|||||||
observer.disconnect()
|
observer.disconnect()
|
||||||
observer = null
|
observer = null
|
||||||
}
|
}
|
||||||
|
window.scrollTo(0, 0)
|
||||||
layout.value = layout.value === 'list' ? 'cards' : 'list'
|
layout.value = layout.value === 'list' ? 'cards' : 'list'
|
||||||
localStorage.setItem('layout', layout.value)
|
localStorage.setItem('layout', layout.value)
|
||||||
await nextTick()
|
await nextTick()
|
||||||
|
|||||||
Reference in New Issue
Block a user