From d44a61a2b4e6b59ed6bebfe64d6b2f3a1dbb303d Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Sat, 17 Oct 2026 05:19:51 -0700 Subject: Pager flicks are judged by when the finger moved, not when the move was handled; the counter counts the reachable posts again. Right after a refresh, with clips warming, touch moves queue behind other work and arrive in bursts. The flick's speed was timed on handling, so a burst after a stall read as a fling (a short flick flew) and a stall before the last move as a crawl (a long flick took one step) (Adam, 2026-10-17: "sometimes a quick long flick only proceeds to the next video and doesn't coast as i would expect it to and sometimes the opposite happens -- a short flick does fly"). Each move is now timed by its event's timeStamp, when the finger made it; moves that share one (synthetic ones can) fall back to the handling time. The counter goes back to counting the posts in the carousel (e529ab1 undone): counting the ones still warming confused, since they can't be scrolled to (Adam: "maybe we should go back to showing the total loaded"). tools/pager-swipe-fly-test.js: a gentle swipe whose moves are handled in one burst goes one post; a fast flick whose last move is handled 300 ms late still flies (it took one step with the old timing). pager-ready-gate is back to "the counter grew". pager-ready-gate, pager-tap-slop, pager-seek-hide, pager-first-frame, thread-pager and profile-pager pass. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_013ZDf1cyCQLkfjftYhymZAg --- src/features/messages.js | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) (limited to 'src/features') diff --git a/src/features/messages.js b/src/features/messages.js index 0ea7520..76330a4 100644 --- a/src/features/messages.js +++ b/src/features/messages.js @@ -13194,14 +13194,12 @@ export function messagesFeature(ctx) { const slide = rowSlide(group); if (slide) { pagerShow(slide); pagerArrive(slide); } } - // Counted: every post the pager has found, the ones still waiting for - // their clip to be ready included — only those kept out for their shape - // aren't. Counting the carousel alone, a refresh showed "1 / 2" over a - // grid of a dozen clips, the total creeping up as clips warmed (Adam, - // 2026-10-17: "the total count persists"). + // Counted: the posts in the carousel — the ones that can be reached. (All + // the posts found, the waiting ones too, was tried and undone: a count + // that can't be scrolled to confused — Adam, 2026-10-17.) function pagerPosition() { if (!pager) return; - const groups = pagerGroups(true).filter((g) => !g.classList.contains('mp-off')); + const groups = pagerGroups(); const slide = pager.cur || pager.anchor; const index = groups.indexOf(slide && slide.closest('.mp-group')); pager.el.querySelector('.mp-position').textContent = (index < 0 ? 0 : index + 1) + ' / ' + groups.length; @@ -13312,7 +13310,15 @@ export function messagesFeature(ctx) { const delta = d.axis === 'y' ? dy : dx; d.far = Math.max(d.far || 0, Math.hypot(dx, dy)); if (d.axis === 'y') d.box.scrollTop = d.start - delta; else d.box.scrollLeft = d.start - delta; - d.track.push({ t: performance.now(), v: delta }); // (when handled: synthetic moves can share a timeStamp) + // Timed when the finger moved (the event's timeStamp), not when the + // move was handled: right after a refresh, with clips warming, moves + // queue behind other work and arrive in bursts — timed on handling, a + // burst after a stall read as a fling (a short flick flew) and a + // stall at the end as a crawl (a long flick took one step) (Adam, + // 2026-10-17: "sometimes a quick long flick only proceeds to the next + // video … sometimes … a short flick does fly"). The handling time is + // kept for moves that share a timeStamp (synthetic ones can). + d.track.push({ t: e.timeStamp, h: performance.now(), v: delta }); while (d.track.length > 2 && d.track[d.track.length - 1].t - d.track[1].t >= TRACK_MS) d.track.shift(); }, { passive: false }); // let go of a drag: on to the next (or the one before), or back @@ -13349,7 +13355,8 @@ export function messagesFeature(ctx) { const delta = d.axis === 'y' ? t.clientY - d.y : t.clientX - d.x; const size = d.axis === 'y' ? d.box.clientHeight : d.box.clientWidth; const a = d.track[0], b = d.track[d.track.length - 1]; - const vel = a && b && b.t > a.t ? (b.v - a.v) / (b.t - a.t) : 0; + const dt = a && b ? (b.t - a.t >= 8 ? b.t - a.t : b.h - a.h) : 0; + const vel = dt > 0 ? (b.v - a.v) / dt : 0; const tap = d.far < TAP_SLOP && Date.now() - d.at < TAP_MS; const go = !tap && (Math.abs(delta) > size * (d.axis === 'y' ? SWIPE_Y : SWIPE_X) || (Math.abs(delta) >= FLICK_MIN && Math.abs(vel) > FLICK && Math.sign(vel) === Math.sign(delta))); settle(d, go ? (delta < 0 ? 1 : -1) : 0, go ? vel : 0); -- cgit v1.2.3