Skip to content

fix(reader): prevent scroll inertia jumps and smooth deceleration - #805

Open
andyWang1688 wants to merge 1 commit into
codedogQBY:mainfrom
andyWang1688:fix/scrolled-inertia-jumps
Open

andyWang1688 wants to merge 1 commit into
codedogQBY:mainfrom
andyWang1688:fix/scrolled-inertia-jumps

Conversation

@andyWang1688

Copy link
Copy Markdown

Summary

Fix scroll-mode snap-back and abrupt inertia stops introduced by the smooth-reading implementation in #711.

Refs #581. This is a follow-up fix, not a new setting or a change to paginated reading.

Problem

With smooth reading enabled and the reader set to continuous scrolling, releasing a long swipe could jump backward and then trigger an unwanted whole-page transition. In the regression fixture, release at 900px snapped to 620px and then advanced to 1240px.

The drag path updated the actual scroll container, while inertia called scrollBy(), which clamps against stale one-page snap bounds. These bounds are appropriate for paginated swipes, not continuous scrolling.

Additional motion issues were a hard 900ms cutoff, an unweighted average of the last three input events, truncated frame time, and small rounded scroll steps being mistaken for a content boundary.

Changes

  • Use actual scroll-container limits during inertia, matching the drag path.
  • Estimate release velocity from a 100ms time window, including time held still before release.
  • Integrate exponential decay over elapsed time and stop at the existing speed threshold rather than at a fixed duration.
  • Carry subpixel rounding forward so the slow tail does not stop prematurely.
  • Extract the numerical calculations and named constants into a small DOM-independent module; keep scheduling, cancellation and rendering in the paginator.
  • Add dependency-free Node unit tests and a real-paginator browser regression fixture; regenerate the mobile reader bundle.

No changes to the smooth-reading setting/default, paginated swipe logic, chapter preloading, dependencies, or native signing configuration.

Validation

  • 12 unit tests: node --test packages/foliate-js/tests/scroll-inertia.test.js.
  • 8 deterministic browser timing scenarios: 30/60/120Hz, a delayed frame, pause before release, low-speed tail and irregular input intervals.
  • 6 browser behavior scenarios: long swipe, repeated swipes, reverse swipe, inertia disabled, touch-to-cancel and end-of-book clamping.
  • All eight deterministic traces exactly match before/after the final pure-function extraction.
  • Mobile reader rebuild is reproducible; all five generated scripts parse; git diff --check passes.
  • The motion-fix build was installed on an iPhone 14 Pro; the reporter confirmed that jumping was resolved and scrolling felt good. The later behavior-preserving extraction was browser-tested but not reinstalled on the phone.

For browser tests, serve packages/foliate-js over local HTTP, open /tests/scroll-inertia.html, and run await window.runTimingSuite() and await window.runSuite() separately in the console. Each result includes a top-level pass and frame traces.

Scope limits: automated gestures use a single horizontal-writing chapter in Chromium, not physical iOS touch input. Browser rAF was throttled, so behavior tests are not FPS measurements. Cross-chapter transitions and vertical writing are not covered by this fixture.

Use actual content bounds instead of paginated snap bounds during inertia. Estimate release speed over a time window, integrate decay over elapsed time, and preserve subpixel motion. Add pure-function and browser regression coverage and regenerate the mobile reader.

Refs codedogQBY#581. Follow-up to codedogQBY#711.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant