diff options
| author | Adam Mathes <adam@adammathes.com> | 2026-02-16 16:35:38 -0800 |
|---|---|---|
| committer | Adam Mathes <adam@adammathes.com> | 2026-02-16 16:35:38 -0800 |
| commit | 72e131f9c273d15e8d3b5c8a9320ab7fb1d533d4 (patch) | |
| tree | 8d02878300210d412f88d2890e42f3de8f1e8b80 /frontend-vanilla/src/main.ts | |
| parent | f04d8fbd9900d5326cdd65a725e57f4b08bbd655 (diff) | |
| download | neko-72e131f9c273d15e8d3b5c8a9320ab7fb1d533d4.tar.gz neko-72e131f9c273d15e8d3b5c8a9320ab7fb1d533d4.tar.bz2 neko-72e131f9c273d15e8d3b5c8a9320ab7fb1d533d4.zip | |
Fix scroll-to-read functionality across all UIs (V1, V2, V3)
Diffstat (limited to 'frontend-vanilla/src/main.ts')
| -rw-r--r-- | frontend-vanilla/src/main.ts | 50 |
1 files changed, 33 insertions, 17 deletions
diff --git a/frontend-vanilla/src/main.ts b/frontend-vanilla/src/main.ts index c310144..a8606e3 100644 --- a/frontend-vanilla/src/main.ts +++ b/frontend-vanilla/src/main.ts @@ -276,24 +276,40 @@ export function renderItems() { observer.observe(sentinel); } - // Setup item observer for marking read when items scroll past (above viewport) - itemObserver = new IntersectionObserver((entries) => { - entries.forEach(entry => { - if (!entry.isIntersecting && entry.boundingClientRect.bottom < (entry.rootBounds?.top ?? 0)) { - const target = entry.target as HTMLElement; - const id = parseInt(target.getAttribute('data-id') || '0'); - if (id) { - const item = store.items.find(i => i._id === id); - if (item && !item.read) { - updateItem(id, { read: true }); - itemObserver?.unobserve(target); - } - } + // Scroll listener for reading items + // We attach this to the scrollable container: #main-content + if (scrollRoot) { + let timeoutId: number | null = null; + const onScroll = () => { + if (timeoutId === null) { + timeoutId = window.setTimeout(() => { + const containerRect = scrollRoot.getBoundingClientRect(); + + store.items.forEach((item) => { + if (item.read) return; + + const el = document.querySelector(`.feed-item[data-id="${item._id}"]`); + if (el) { + const rect = el.getBoundingClientRect(); + // Mark as read if the top of the item is above the top of the container + if (rect.top < containerRect.top) { + updateItem(item._id, { read: true }); + } + } + }); + timeoutId = null; + }, 250); } - }); - }, { root: scrollRoot, threshold: 0 }); - - contentArea.querySelectorAll('.feed-item').forEach(el => itemObserver!.observe(el)); + }; + // Remove existing listener if any (simplistic approach, ideally we track and remove) + // Since renderItems is called multiple times, we might be adding multiple listeners? + // attachLayoutListeners is called once, but renderItems is called on updates. + // We should probably attaching the scroll listener in the layout setup, NOT here. + // But we need access to 'items' which is in store. + // Let's attach it here but be careful. + // Actually, attaching to 'onscroll' property handles replacement automatically. + scrollRoot.onscroll = onScroll; + } } export function renderSettings() { |
