mirror of
https://github.com/hoornet/vega.git
synced 2026-07-29 03:08:10 -07:00
Feed virtualization Stage 2: infinite scroll
Adds older-notes pagination to the Global feed. fetchGlobalFeed gains an optional until param (fetch events before a timestamp, no since bound). The feed store's new loadOlderNotes action fetches 50 older notes when triggered, dedups, merges, re-sorts. MAX_FEED_SIZE raised 200 to 1000 — virtualization bounds the DOM-node/bitmap count, so this just caps the JS notes array as hygiene. Feed.tsx auto-triggers loadOlderNotes when the user scrolls within ~8 rows of the bottom; a 'Loading older notes' row shows during the fetch. Global tab only (Following uses a separate path, Trending is a ranked snapshot). Pending: sandboxed memory verification.
This commit is contained in:
@@ -34,6 +34,8 @@ export function Feed() {
|
||||
const connect = useFeedStore((s) => s.connect);
|
||||
const loadCachedFeed = useFeedStore((s) => s.loadCachedFeed);
|
||||
const loadFeed = useFeedStore((s) => s.loadFeed);
|
||||
const loadOlderNotes = useFeedStore((s) => s.loadOlderNotes);
|
||||
const loadingOlder = useFeedStore((s) => s.loadingOlder);
|
||||
const trendingNotes = useFeedStore((s) => s.trendingNotes);
|
||||
const trendingLoading = useFeedStore((s) => s.trendingLoading);
|
||||
const loadTrendingFeed = useFeedStore((s) => s.loadTrendingFeed);
|
||||
@@ -166,6 +168,18 @@ export function Feed() {
|
||||
if (focusedNoteIndex >= 0) virtualizer.scrollToIndex(focusedNoteIndex, { align: "center" });
|
||||
}, [focusedNoteIndex, virtualizer]);
|
||||
|
||||
// Infinite scroll (Global tab only): when the user nears the bottom of the
|
||||
// virtualized list, load the next page of older notes. loadOlderNotes
|
||||
// self-guards against concurrent calls and end-of-feed.
|
||||
const virtualItems = virtualizer.getVirtualItems();
|
||||
useEffect(() => {
|
||||
if (tab !== "global") return;
|
||||
const last = virtualItems[virtualItems.length - 1];
|
||||
if (last && last.index >= filteredNotes.length - 8) {
|
||||
loadOlderNotes();
|
||||
}
|
||||
}, [virtualItems, filteredNotes.length, tab, loadOlderNotes]);
|
||||
|
||||
return (
|
||||
<div className="h-full flex flex-col">
|
||||
{/* Header */}
|
||||
@@ -307,7 +321,7 @@ export function Feed() {
|
||||
{/* Virtualized list — only the visible window of cards stays in the DOM */}
|
||||
{filteredNotes.length > 0 && (
|
||||
<div style={{ height: `${virtualizer.getTotalSize()}px`, position: "relative", width: "100%" }}>
|
||||
{virtualizer.getVirtualItems().map((vi) => {
|
||||
{virtualItems.map((vi) => {
|
||||
const event = filteredNotes[vi.index];
|
||||
return (
|
||||
<div
|
||||
@@ -326,6 +340,10 @@ export function Feed() {
|
||||
})}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{tab === "global" && loadingOlder && (
|
||||
<div className="py-4 text-center text-text-dim text-[12px]">Loading older notes…</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user