Add continuous scrolling for multi-page documents - #699
Conversation
7798537 to
e38cae2
Compare
|
I tested your PR using app/src/androidTest/assets/test-multipage.pdf . There are panning issues when zoomed in when the viewer is at page 4 of the test pdf file. |
# Conflicts: # app/src/androidTest/kotlin/app/grapheneos/pdfviewer/test/PdfViewerMenuStateTest.kt # app/src/androidTest/kotlin/app/grapheneos/pdfviewer/util/PdfViewerRobot.kt # app/src/androidTest/kotlin/app/grapheneos/pdfviewer/util/PdfViewerTestUtils.kt # app/src/main/java/app/grapheneos/pdfviewer/PdfViewer.java # app/src/main/java/app/grapheneos/pdfviewer/viewModel/PdfViewModel.kt # app/src/main/res/menu/pdf_viewer.xml # viewer/js/index.js
|
@rdevshp the issue should be addressed now, could you confirm |
There are still panning issues when zoomed in at page 4 of test-multipage.pdf. When I swipe left, the viewer would very often suddenly become a blank page. Also when I swipe left/right, it would go to the next/previous page, but I don't think that is desirable for the continuous scrolling mode. |
|
@aljazceru Are you still working on this PR? |
|
@rdevshp yes sorry, been busy, i have updates i'll push in the next days |
# Conflicts: # app/src/androidTest/kotlin/app/grapheneos/pdfviewer/test/PdfViewerEdgeToEdgeTest.kt # app/src/androidTest/kotlin/app/grapheneos/pdfviewer/util/PdfViewerRobot.kt # app/src/main/java/app/grapheneos/pdfviewer/PdfJsChannel.kt # app/src/main/java/app/grapheneos/pdfviewer/PdfViewerScreen.kt # app/src/main/java/app/grapheneos/pdfviewer/viewModel/PdfViewModel.kt # app/src/main/res/values/strings.xml # viewer/css/pdf_viewer.css # viewer/js/index.js # viewer/js/index.test.js
Recovered from the stale .worktrees/upstream-port working tree (never committed to any branch): - index.js: expand page-wrapper to canvas width for over-wide (zoomed) pages so the whole canvas area is scrollable - index.test.js: assert wrapper width tracks over-wide canvas - PdfViewerScreen: disable fling page-jump while in continuous mode - Robot: performSwipeLeft helper (Direction import) - MultiPageRenderTest: horizontalFling_continuousModeDoesNotChangePage; drive zoom test through the custom-zoom menu UI (300%) - NavigationTest: run the fling-navigation test in single-page mode, since continuous mode now pans instead of jumping pages
Restores the product decision from 'fix panning issues' (3ba62c6): new documents open in fit-width (mode 2), not fit-page (mode 1). Caught by PdfViewerPageFitModeTest.fitWidthMode_isDefaultForNewDocument failing on the Pixel 9a during the manual device test pass.
Zoom changes and other re-renders cleared the visible canvas before the
asynchronous pdf.js render produced the new bitmap, leaving a blank page
for the duration of the render. On slower devices (CI emulator) that
window is long enough to be clearly visible — the exact 'suddenly a
blank page' symptom from the PR review when panning a zoomed page.
Render into an offscreen canvas and swap the finished bitmap into the
visible canvas in one step instead:
- renderPageContent renders into p.renderCanvas and copies it to the
visible canvas when the render task completes
- rerenderVisible no longer clears near pages; it just invalidates the
rendered flag so the old frame stays visible until the swap
- clearPage frees the offscreen target along with the visible canvas
- new JS test: the visible canvas must never drop to width 0 while a
re-render is in flight
Fixes the CI failure in zoomedLastPage_canPanToBothHorizontalEdges
('Canvas was cleared while its zoomed content was visible') and the
blank-page panning report on the upstream PR.
In onRenderPage's zoom path, relayoutAll() resized every page wrapper and rerenderVisible() ran while the scroll position still described the old layout. The page under the viewport therefore measured as 'far' in the new geometry and was cleared, while unrelated pages nearer the stale offset were rendered instead — the viewport went blank exactly when a zoomed page re-rendered. On fast devices the follow-up render hides the gap; on slower ones (CI emulator, and per the upstream review report, real devices while panning) the blank page is clearly visible. Move the focus-preserving scrollBy ahead of rerenderVisible so near/far decisions are made against the re-anchored scroll position. Reproduced and verified on a local API 36 x86_64 emulator: zoomedLastPage_canPanToBothHorizontalEdges now passes, full instrumented suite green.
d3b29f6 to
f106a2b
Compare
both issues are addressed with the latest commit @rdevshp |
Summary
Why
Large documents exposed two races in the continuous renderer. Repeated pinch events could queue enough WebView/JavaScript work to delay state reads, and a late-page jump could run before progressive page setup created the target wrapper. The scroll handler could then overwrite the requested page.
Zoom rendering now keeps one request in flight and coalesces pending updates. Page requests remain sticky until the target is laid out. Rendering and relayout are limited to the visible page window.
Validation
npm test -- --reporter=dot— 14 tests passednpx eslint ../gradlew :app:lintDebug :app:assembleDebug :app:assembleDebugAndroidTest --no-daemonANDROID_SERIAL=5A011JEBF06589 ./gradlew connectedDebugAndroidTest --no-daemon— 77 tests passed on a Pixel 9agit diff --check