From 2153f7cc0cfb9b30965e6052c00ac36f0e5e64c8 Mon Sep 17 00:00:00 2001 From: Huang Xin Date: Sun, 21 Jun 2026 13:46:33 +0800 Subject: [PATCH] fix(reader): reset scroll to top on paginated fit-width page turn (#4683) (#4695) In paginated fixed-layout mode (PDF / fixed-layout EPUB) with fit-width zoom, a page taller than the viewport makes the renderer host scroll vertically. Turning the page kept the previous page's vertical offset, so the next page opened scrolled to the end instead of the top. The bug only shows on WebKit (Linux/iOS/macOS), which preserves the scroll offset across the page content swap; Blink (Android/Chrome) resets it to zero. Bump foliate-js to the fix (readest/foliate-js#34): reset scrollTop on a page turn only. Add a unit test for the new computePaginatedScroll helper. Co-authored-by: Claude Opus 4.8 (1M context) --- .../fixed-layout-paginated-scroll.test.ts | 40 +++++++++++++++++++ packages/foliate-js | 2 +- 2 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 apps/readest-app/src/__tests__/document/fixed-layout-paginated-scroll.test.ts diff --git a/apps/readest-app/src/__tests__/document/fixed-layout-paginated-scroll.test.ts b/apps/readest-app/src/__tests__/document/fixed-layout-paginated-scroll.test.ts new file mode 100644 index 00000000..ea9f2b77 --- /dev/null +++ b/apps/readest-app/src/__tests__/document/fixed-layout-paginated-scroll.test.ts @@ -0,0 +1,40 @@ +import { describe, expect, it } from 'vitest'; + +import { computePaginatedScroll } from 'foliate-js/fixed-layout.js'; + +describe('fixed-layout paginated page-turn scroll reset', () => { + it('resets the vertical scroll to the top of the page on a page turn (#4683)', () => { + // A tall fit-width page leaves the host scrolled to the bottom; turning to + // the next page must start at the top, not inherit the previous offset. + expect( + computePaginatedScroll({ + elementWidth: 800, + containerWidth: 800, + scrollTop: 1200, + pageTurn: true, + }), + ).toEqual({ scrollLeft: 0, scrollTop: 0 }); + }); + + it('preserves the vertical scroll on a non-navigation re-render (resize/zoom/theme)', () => { + expect( + computePaginatedScroll({ + elementWidth: 800, + containerWidth: 800, + scrollTop: 1200, + pageTurn: false, + }), + ).toEqual({ scrollLeft: 0, scrollTop: 1200 }); + }); + + it('re-centers horizontally when the page is wider than the viewport', () => { + expect( + computePaginatedScroll({ + elementWidth: 1200, + containerWidth: 800, + scrollTop: 0, + pageTurn: true, + }), + ).toEqual({ scrollLeft: 200, scrollTop: 0 }); + }); +}); diff --git a/packages/foliate-js b/packages/foliate-js index 828d6132..981298cf 160000 --- a/packages/foliate-js +++ b/packages/foliate-js @@ -1 +1 @@ -Subproject commit 828d6132ea4ad973657b68832f18757dbb289f85 +Subproject commit 981298cf4074e4ed61b452de34926deab1b53126