diff options
| author | Adam Soltys <[email protected]> | 2026-10-16 22:13:16 -0700 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2026-10-16 22:13:16 -0700 |
| commit | 7d09e7f2b01f72db518f7cf906d887c22a49387e (patch) | |
| tree | 2ea6d565bf6518ca6c471b43a339a710d3f90024 /tools | |
| parent | 550bd5cb8be1a879083d987edca7b4e676ac3557 (diff) | |
| download | coinosv3-7d09e7f2b01f72db518f7cf906d887c22a49387e.tar.gz coinosv3-7d09e7f2b01f72db518f7cf906d887c22a49387e.zip | |
The wheel coasts wherever the pointer is while a feed or a thread is up.
The coast only took a notch whose target sat inside the feed or the thread, so a pointer resting on the rail, the header or the wallet column beside the feed on a wide screen got the browser's plain scroll (Adam, 2026-10-16: "when my cursor is hovered over the right side bar or any part of the page that's not the feed, wheeling scrolls without coasting. can we make it coast no matter where my pointer is?"). Now the question is whether a feed or a thread is the page on screen; the pointer's spot only matters when it is over something that takes the wheel itself — a text box, the chips strip, the lightbox, the pager, a box that scrolls on its own — and on a page with no feed on it (the wallet) the wheel stays the browser's.
feed-wheel-reverse-test: the fixture's page carries a feed unless told otherwise; a notch with the pointer over the wallet column, or over nothing in particular, coasts; one on a page without a feed does not.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01J1Kon8bxJoHRpJdSzshCkp
Diffstat (limited to 'tools')
| -rw-r--r-- | tools/feed-wheel-reverse-test.js | 19 |
1 files changed, 12 insertions, 7 deletions
diff --git a/tools/feed-wheel-reverse-test.js b/tools/feed-wheel-reverse-test.js index 352bc0e..80e2fde 100644 --- a/tools/feed-wheel-reverse-test.js +++ b/tools/feed-wheel-reverse-test.js @@ -5,16 +5,18 @@ const source = await Bun.file('src/app.js').text(); const start = source.indexOf('(() => {', source.indexOf('// The feed scrolls like a phone')); const end = source.indexOf("\nwindow.addEventListener('load'", start); assert(start > 0 && end > start); -function fixture(inside = '') { +function fixture(inside = '', { feedOnPage = true } = {}) { let now = 100, id = 0; const handlers = new Map(), frames = new Map(), steps = []; const window = { scrollY: 5000, addEventListener: (name, fn) => handlers.set(name, fn), scrollBy: ({ top }) => { steps.push(top); window.scrollY += top; }, }; - const document = { body: {}, addEventListener() {}, removeEventListener() {} }; - // the target sits in a feed page (or, for a thread case, a thread page), inside the given element - const target = { closest: (selector) => selector.split(/,\s*/).some((p) => p === inside || (p === '.feed-page' && inside !== '.thread-page')) ? target : null, + // the page shows a feed (or, for a thread case, a thread) unless told otherwise + const document = { body: {}, addEventListener() {}, removeEventListener() {}, + querySelector: (selector) => (feedOnPage && selector.split(/,\s*/).some((p) => p === (inside === '.thread-page' ? '.thread-page' : '.feed-page')) ? {} : null) }; + // the target sits inside the given element (over the posts unless it names something else) + const target = { closest: (selector) => selector.split(/,\s*/).some((p) => p === inside) ? target : null, scrollHeight: 100, clientHeight: 100, parentElement: document.body }; runInNewContext(source.slice(start, end), { window, document, matchMedia: () => ({ matches: false }), performance: { now: () => now }, @@ -76,16 +78,19 @@ for (const dir of [1, -1]) { } // A notch over a video (or an audio player) in the feed coasts like any // other — the wheel does nothing to a player itself — and so does one on a -// thread page. -for (const sel of ['video', 'audio', '.thread-page']) { +// thread page, and one with the pointer anywhere else on the page while a +// feed is up (the rail, the wallet column, the header). +for (const sel of ['video', 'audio', '.thread-page', '.wallet-column', '']) { const f = fixture(sel); const y = f.y; f.wheel(1); settle(f); assert(f.y - y > 280 && f.y - y < 330, 'a notch over ' + sel + ' coasts a full push: ' + (f.y - y)); } -// ...while a notch in a text box, or in the media pager, is left alone. +// ...while a notch in a text box, or in the media pager, is left alone — and +// so is every notch on a page with no feed on it (the wallet). for (const sel of ['textarea', '.media-pager']) { const f = fixture(sel); const y = f.y; f.wheel(1); settle(f); assert.equal(f.y, y, 'a notch in ' + sel + ' is not ours'); } +{ const f = fixture('', { feedOnPage: false }); const y = f.y; f.wheel(1); settle(f); assert.equal(f.y, y, 'no feed on the page: the wheel is the browser\'s'); } console.log('✓ a turn back against a flight brakes, the next notch is the gentle start, then the wind-up; against a stroll or a dead coast the gentle start at once; stale frames; videos and threads coast'); |
