fix(library): the wall takes a step off a single row, and a year of four frames stops stranding the shelf

This commit is contained in:
2026-10-12 19:57:18 +07:00
parent c88d43a158
commit 73d1c22c30
+24 -8
View File
@@ -4076,13 +4076,13 @@ function useWallWindow(count: number, on: boolean): { ref: RefObject<HTMLDivElem
// run is a count the window feeds itself with. This is the same read the
// settle effect above scrolls the wall by.
const cols = Math.max(1, getComputedStyle(now).gridTemplateColumns.split(' ').length);
// The run the step below is read off. A run of a single row is no run at
// all — that is the last row of a shelf scrolled to its end — and a wall
// that has drawn nothing is nothing to read: the state's own first
// screenful stands until there is one.
// The run the step below is read off. A wall that has drawn nothing is
// nothing to read — the state's own first screenful stands — but a run of a
// single row is not nothing: it is the last row of a shelf scrolled to its
// end, or the whole wall of a shelf of four frames. It has no average, and
// the step it gets instead is its own height (below).
const cards = now.querySelectorAll<HTMLElement>(':scope > .adm-card');
const rowsDrawn = Math.floor(cards.length / cols);
if (rowsDrawn < 2) return;
// The step from one row to the next, taken as the drawn run's own average.
// The cards do NOT all stand the same height — a caption that wraps makes
// its row taller — and `offsetTop` is rounded to whole pixels, so the
@@ -4098,15 +4098,31 @@ function useWallWindow(count: number, on: boolean): { ref: RefObject<HTMLDivElem
// changes a card's own height (a caption wraps at the width it is given); a
// resize that does not re-column keeps the step, and a spacer a few pixels out
// is a scrollbar a few pixels out, not a blank screen.
if (colsRef.current !== cols) {
if (colsRef.current !== cols && rowsDrawn >= 2) {
const drawn = (cards[(rowsDrawn - 1) * cols].getBoundingClientRect().top - cards[0].getBoundingClientRect().top) / (rowsDrawn - 1);
if (drawn > 0) {
colsRef.current = cols;
pitchRef.current = drawn;
}
}
const pitch = pitchRef.current;
if (!(pitch > 0)) return;
// And the one-row run, which has no average to take: its own height is the
// step — one card plus the gap, the same fallback the settle effect takes.
// Returning here instead is a window that cannot grow, and there is a shelf
// it strands: the reset above puts a year of four frames at {0, 4}, one row
// of five columns, no average — and every pass after it reads that one row
// and leaves, so the shelf stands at four cards for the rest of the visit;
// another year, another folder, a reset, all four cards under a count of six
// hundred. The step is a guess, and a spacer a few pixels out is a scrollbar
// a few pixels out; a window left alone is the wall.
let pitch = pitchRef.current;
if (!(pitch > 0) || colsRef.current !== cols) {
const first = cards[0];
if (!first) return;
pitch = first.offsetHeight + WALL_GAP;
if (!(pitch > 0)) return;
colsRef.current = cols;
pitchRef.current = pitch;
}
const rows = Math.ceil(count / cols);
const row0 = Math.max(0, Math.floor(now.scrollTop / pitch) - WALL_ROWS);
const row1 = Math.min(rows, Math.ceil((now.scrollTop + now.clientHeight) / pitch) + WALL_ROWS);