diff options
| -rw-r--r-- | src/features/messages.js | 17 | ||||
| -rw-r--r-- | tools/pager-swipe-fly-test.js | 2 |
2 files changed, 16 insertions, 3 deletions
diff --git a/src/features/messages.js b/src/features/messages.js index 76330a4..cf6e2c7 100644 --- a/src/features/messages.js +++ b/src/features/messages.js @@ -13172,7 +13172,7 @@ export function messagesFeature(ctx) { if (land) slideFrame(land, -1); pagerGlide(pager.scroller, 'y', dest, vel, { ms: screens > 1.05 ? Math.min(most, 100 + pace * screens) : 0, - onDone: () => { if (!pager) return; pager.flying = false; const s = pagerHere(); if (s && s !== pager.cur) pagerArrive(s); }, + onDone: () => { if (!pager) return; pager.flying = false; const s = pagerHere(); if (s && s !== pager.cur) pagerArrive(s); pagerPosition(); }, }); } const pagerArrive = (slide) => { if (pager && pager.arrive) pager.arrive(slide); }; @@ -13201,13 +13201,24 @@ export function messagesFeature(ctx) { if (!pager) return; 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; + let index = groups.indexOf(slide && slide.closest('.mp-group')); + // in a flight, the post passing under the reader: the count runs with + // the slides rather than jumping on landing (Adam, 2026-10-17: "the + // counter should animate as we fly") + if (pager.flying && groups.length) { + const y = pager.scroller.scrollTop + pager.scroller.clientHeight / 2; + let lo = 0, hi = groups.length - 1; // the last post whose top is above the middle of the screen + while (lo < hi) { const m = (lo + hi + 1) >> 1; if (groups[m].offsetTop <= y) lo = m; else hi = m - 1; } + index = lo; + } + const text = (index < 0 ? 0 : index + 1) + ' / ' + groups.length, el = pager.el.querySelector('.mp-position'); + if (el.textContent !== text) el.textContent = text; } function buildPager(want) { const video = want.kind === 'videos'; const scroller = h('div', { class: 'mp-scroll' }); + scroller.addEventListener('scroll', () => { if (pager && pager.flying) pagerPosition(); }, { passive: true }); const el = h('div', { class: 'media-pager' + (video ? ' videos' : '') + (pagerLoud ? '' : ' quiet'), role: 'dialog', 'aria-modal': 'true' }, scroller, h('div', { class: 'mp-position', role: 'status' }, '0 / 0'), diff --git a/tools/pager-swipe-fly-test.js b/tools/pager-swipe-fly-test.js index cae3536..418b8e4 100644 --- a/tools/pager-swipe-fly-test.js +++ b/tools/pager-swipe-fly-test.js @@ -108,11 +108,13 @@ try { console.log('\n[a fast flick: several posts, landing snapped]'); const trace = async (sw) => { await page.evaluate(() => { const sc = document.querySelector('.mp-scroll'); window.__tr = []; const t0 = performance.now(); const rec = () => { window.__tr.push(sc.scrollTop); if (performance.now() - t0 < 1500) requestAnimationFrame(rec); }; requestAnimationFrame(rec); }); await sw(); await sleep(1600); return page.evaluate(() => window.__tr); }; + await page.evaluate(() => { const el = document.querySelector('.mp-position'); window.__counts = [el.textContent]; new MutationObserver(() => { if (window.__counts.at(-1) !== el.textContent) window.__counts.push(el.textContent); }).observe(el, { childList: true, characterData: true, subtree: true }); }); const tr = await trace(() => swipe(600, 80, 3)); await settled(); // three big moves: 3–6 px/ms as their handling takes, a long coast's worth (past the nine loaded, maybe) const landed = await at(); check('a 600px flick in a few frames flies several posts on', landed !== 'between' && landed >= 5, String(landed)); check('…landing square on a post', landed !== 'between'); check('…in a glide, never back', tr.every((x, i) => !i || x >= tr[i - 1] - 0.5), tr.slice(0, 12).map((x) => Math.round(x)).join(' ')); + check('the counter ran through the posts on the way, not jumping on landing', (await page.evaluate(() => window.__counts)).length >= 4, (await page.evaluate(() => window.__counts)).join(' → ')); const seen = await page.evaluate(() => document.querySelector('.mp-position').textContent); check('the counter says where it landed', seen === landed + ' / ' + N, seen); |
