Commit Graph
5 Commits
Author SHA1 Message Date
peter d065902404 refactor(feed): cap the read-ahead lookahead and extract it to a tested helper
Review follow-up. The viewport-scaled lookahead was unbounded, so a tall window
prefetched several feed pages on every mount / filter change before any scroll —
wasted work on the app's heaviest query. Clamp it to MAX_LOOKAHEAD_ROWS, and move
the policy into a pure readAhead.ts (readAheadLookahead / shouldPrefetchNext) with
unit tests covering the floor, the scaling, the cap boundary, and the fetch trigger
— the core of the feed-scroll fix now has coverage instead of only manual E2E.
2026-08-19 01:32:26 +02:00
peter a300977ed4 fix(feed): read further ahead so fast scrolling doesn't stall at "Load more"
Keyset pagination is strictly serial (a page needs the previous page's cursor)
and the read-ahead only fired within a fixed 4 rows of the loaded end, pulling
one 60-item page per cycle. A fast free-spin flick (MX Master & co.) out-scrolls
that tiny lookahead, lands on an empty bottom, and waits out a chain of serial
round-trips — the multi-second "Load more" hang. Scale the lookahead to the
rendered row count (PREFETCH_VIEWPORTS screenfuls); since the effect re-runs when
a page settles it chains, keeping a couple of screens buffered ahead of the fold
so the content is usually already there. Bounded, and a no-op for finite lists.
2026-08-19 01:13:57 +02:00
peter e257e2aca0 style(frontend): Prettier config + one-time repo-wide format pass
Prettier 3 (pinned), printWidth 100, double quotes — chosen to match the existing
hand-formatting and minimise reflow. This commit is ONLY the mechanical format pass
(`prettier --write`) plus the config/ignore/scripts, isolated so it never pollutes a
feature diff. Verified behaviour-neutral: typecheck, eslint (0 errors), and vitest
all green before and after. See .git-blame-ignore-revs — `git blame` skips this sha.
2026-07-21 02:26:40 +02:00
peter c630d29ff6 fix(managers): address the E4 S3 code-review round 2 findings
- The portalled tag picker now FOLLOWS its trigger on scroll (rAF-coalesced)
  instead of closing. Closing on every wheel tick was a regression for the table,
  where the menu used to travel with its row; it still closes once the trigger
  leaves the viewport (nothing left to anchor to) or on resize.
- Place the menu by MEASUREMENT, not a px estimate: it opens below, then the
  layout effect flips it above only if the real box overflows. The old
  `rows * 30px` guess read short at font-scale 1.3 (the rows are rem), which
  could leave a fixed menu hanging off the bottom with no way to reach it.
- `toggle` only opens once a position exists, so the `open && coords` gate can
  never show a stale anchor.
- One owner for "is there anything to page": `hasPagerContent()` lives in Pager
  and DataTable calls it, instead of both re-deriving the rule — that drift is
  what left empty control bands behind in the first place.
- Reset the card page on the row COUNT too, not just the filter inputs, so an
  unsubscribe or a shrinking refetch can't leave a stale page to spring back.
- `parseCardSize` clamps to the sizes the pager actually offers (like clampView /
  clampStatus), so the select can't display one value while the grid pages by another.
- VirtualGrid's docblock now carries the stacking-context constraint: its rows are
  transformed, so anything floating an item renders must portal out.
2026-07-20 00:56:47 +02:00
peter 5ea82095a1 refactor(feed): extract virtualization engine into a generic VirtualGrid<T>
VirtualFeed becomes a thin wrapper that maps a FeedView to VirtualGrid's
layout spec and renders a VideoCard per item; all measure/chunk/place/
infinite-scroll mechanics move to VirtualGrid so the channel manager (E4 S3)
can reuse them. Behaviour-preserving: e2e 17/17, all render families smoked.
2026-07-19 21:36:54 +02:00