fix(feed): width-change measurement invalidation + best-effort SSE counts
Post-commit review follow-ups for the batch-3 feed work.
Frontend — VirtualFeed: the guarded setOptions keyed only on (count, scrollMargin),
so a rotation (or the first-paint 0->real container width) changed colWidth / card
heights without invalidating the cached measurements, leaving getTotalSize and the
scrollbar stale until each row scrolled back through the window. Track appliedWidth
and call virtualizer.measure() on a width delta so heights re-estimate at the new
width (rendered rows re-measure immediately via their ResizeObserver). Covers list +
grid and the first-paint 120px-estimate case.
Backend — social.rs: the fresh like/comment count SELECT used `.await?`, so a
transient DB failure would 500 the request after the like/comment had already
committed. Make the count + broadcast best-effort (if let Ok { ... }); the mutation
succeeds regardless and the next event / pull-to-refresh reconciles the count.
Docs — FOLLOWUPS: record the review findings left as-is (grid-prepend tile reflow,
filtered-grid auto-load which is pre-existing, comment-delete stale count, and the
last-write-wins count ordering note).
Verified: svelte-check 0 errors, cargo build clean.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -106,23 +106,33 @@
|
||||
// this effect (that would loop).
|
||||
let appliedCount = -1;
|
||||
let appliedMargin = Number.NaN;
|
||||
let appliedWidth = Number.NaN;
|
||||
|
||||
function applyOptions() {
|
||||
const count = rowCount;
|
||||
const width = containerWidth;
|
||||
const margin = listEl ? listEl.getBoundingClientRect().top + window.scrollY : 0;
|
||||
scrollMargin = margin; // drives the template transforms
|
||||
if (count === appliedCount && Math.abs(margin - appliedMargin) < 0.5) return;
|
||||
// A width change (rotation, or the first 0→real clientWidth landing) changes
|
||||
// every card's / tile-row's real height, so the heights cached from the old
|
||||
// width are stale even when count and margin are unchanged. Invalidate the
|
||||
// measurement cache so getTotalSize + positions recompute (rendered rows then
|
||||
// re-measure immediately via their ResizeObserver) instead of trusting them.
|
||||
const widthChanged = width > 0 && Math.abs(width - appliedWidth) > 0.5;
|
||||
if (count === appliedCount && Math.abs(margin - appliedMargin) < 0.5 && !widthChanged) return;
|
||||
appliedCount = count;
|
||||
appliedMargin = margin;
|
||||
appliedWidth = width;
|
||||
get(virtualizer).setOptions({ count, scrollMargin: margin });
|
||||
if (widthChanged) get(virtualizer).measure();
|
||||
}
|
||||
|
||||
// Re-apply when the row count or column width changes (load-more, prepend,
|
||||
// delete, filter, rotate). `colWidth`/`rowCount` are the only tracked reads, so a
|
||||
// length-stable like/comment patch doesn't re-run this.
|
||||
// Re-apply when the row count or container width changes (load-more, prepend,
|
||||
// delete, filter, rotate). `containerWidth`/`rowCount` are the only tracked
|
||||
// reads, so a length-stable like/comment patch doesn't re-run this.
|
||||
$effect(() => {
|
||||
void rowCount;
|
||||
void colWidth;
|
||||
void containerWidth;
|
||||
applyOptions();
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user