Repository navigation
feat: two-page comic spreads on unfolded foldables and landscape tablets (stacked on #300, refs #286) - #304
Conversation
162e427 to
106129b
Compare
106129b to
3fc7627
Compare
|
Thanks @chortya, the comic spread implementation and test coverage look thorough, especially the hinge handling and spread re-pairing cases. When reviewing the code, I found one account-isolation issue in Could you scope this store key to the active server profile/provider, similar to the other account-owned reader state, and add a cross-profile regression test? |
3fc7627 to
331f134
Compare
|
Thanks, good catch. Rebased onto current
Verified: JVM tests, lint, androidTest compile, and all 25 tests in |
|
Thanks @chortya, the comic spread implementation and test coverage look thorough. I found no functional blockers in the source review. Before merge, please remove these generated Python bytecode files from the PR:
The JVM tests, Android test compilation, debug build, and CI check pass. The connected tests were not independently validated on my attached Samsung device because Espresso failed before reaching the test assertions with the existing |
Add a Compose spread pager for paginated CBZ/CBR when the spread policy applies: cover-alone and shift pairing, wide pages shown alone with live re-pairing, RTL page order, hinge-aware gutter, bounded pinch zoom, tap-zone/volume/page-list navigation by spread, per-page long-press export, first-page resume and last-visible-page progress. Includes unit, Compose UI and device-level spread/OLED instrumented tests. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Existing comic navigator tests now pin twoPageSpread=OFF so they test the Readium image navigator on any window size; add spread-mode center tap and pinch-zoom paging-lock tests. Use a gesture-local zoom scale so fast pinches do not compound a stale scale. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Posture changes are applied only while the reader is started, and a debounced change landing after onSaveInstanceState no longer runs a fragment transaction; the next start re-checks the spread. - The gutter is re-measured when the hinge changes without a rebuild. - Tap-zone layout and inversion changes apply to the spread on screen, and long-press uses the current bitmaps (rememberUpdatedState). - Prefetch decodes are bounded to two at a time. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Show cover alone and Shift page pairs (per library) next to the shared Two-page spread switch; the library summary reflects EPUB or comic paginated layout. - readerSpreadGutterPx keeps a separating hinge free of artwork. - ComicSpreadActivityInstrumentedTest: spread on a large window and resume after recreation, setting off keeps the Readium navigator, rotate-to-portrait fallback. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ocale, and long-press the page under the finger - Wide (double-page) pages are remembered per book (ComicWidePageStore), so pages decoded in an earlier session still shape the pairing and a reopened book shows the same facing pages. - The spread reader lays out left-to-right regardless of the device locale: page order, swipe direction and hit-testing already follow the book's reading direction, and an RTL locale mirrored them again. - Long-press undoes zoom and pan and splits at the actual gutter, so an off-centre hinge or a zoomed spread exports the page that is shown. - The long-press tests wait for the pressed page's bitmap instead of racing its decode. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
FoldingFeature bounds are window coordinates; the gutter is measured inside the reader. When the reader is inset from the window's left edge the hinge is shifted by that offset, and a change of offset re-measures the gutter. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… zoom - A pairing change during a swipe or animated page turn lets the turn land instead of jumping back to the previously settled spread. - Zoom is reset only when the visible spread changes, so it stays in step with the spread's pan offset when a page elsewhere turns out wide. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…rror
The spread footer ("Pages 2–3 of 40") and its spoken label, the "Show cover
alone" and "Shift page pairs" settings, and the spread reader's page-load
error and Retry button now use string resources, with Simplified Chinese
translations so the localization check passes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ComicWidePageStore was keyed only by bookId|fileId, so the same book ID on another server or account inherited the previous profile's double-page classifications and paired its pages wrongly. The store is now keyed by the active server profile (which also fixes the provider) as well as the book, the same boundary the per-book EPUB language uses. Saving an empty set removes the entry. Tests: per-profile keys (JVM), two profiles keeping separate classifications, and a reader opened with wide pages remembered only for another profile pairing as if none were remembered (connected). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Apps targeting SDK 36 cannot request a fixed orientation on large screens, so setting requestedOrientation no longer rotates an unfolded foldable and the EPUB and comic "rotated to portrait" tests timed out. They now turn the device a quarter turn through UiAutomation and unfreeze rotation after each test. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
331f134 to
1e2e0ef
Compare
|
Rebased onto current |
|
Thanks, @chortya. The implementation and tests look good. Since the generated bytecode files are still in the PR, would you prefer to remove them in a follow-up PR after this one merges, or update this PR before merge? |
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Thanks, and sorry about that. They were Python |
Contribution pause
The maintainer lifted the pause and invited split PRs in #286.
Summary
On an unfolded foldable or a landscape tablet, paginated CBZ/CBR/CB7 shows facing pages like a printed book. The same
Two-page spread when unfoldedswitch as EPUB controls it.comicSpreads()pairingShow cover alone, default on), double-page (landscape) images alone with the following pairs re-aligned, optional one-page shift (Shift page pairs), right-to-left libraries put the earlier page on the right.ComicSpreadReaderPages N–M of T.ComicWidePageStore) so a reopened book shows the same facing pages.readerSpreadGutterPx, hinge converted from window to reader coordinates); otherwise the pages meet with no gap. A hinge change re-measures the gutter without a rebuild.onSaveInstanceStatewaits for the next start instead of running a fragment transaction (that crashed the fork build).PDF stays single-page. New test dependency:
androidx.window:window-testing1.5.1, used to simulate fold postures.Verification
./gradlew :app:testDebugUnitTest— 1005/1005 pass (newComicSpreadPairingTest,ComicSpreadLayoutTest, gutter cases inReaderSpreadPolicyTest, comic settings inLibraryReaderPreferencesTest).:app:lintDebug— 0 errors.:app:assembleDebugsucceeds. No added trailing whitespace; line endings preserved.Connected, Pixel Fold API 36 emulator unfolded (2208×1840):
ComicSpreadActivityInstrumentedTest4/4 — spread on the unfolded window and resume after recreation, a remembered wide page keeps the same pairs on reopening, setting off keeps the Readium navigator, rotate-to-portrait fallback.ComicSpreadReaderInstrumentedTest12/12 — pairing, navigation, tap zones applied to the spread on screen, hinge re-measure, long-press in RTL books, an RTL device locale not mirroring the spread (fails without the fix), half-width decodes, pinch-zoom locking swipes, re-pairing after a wide page is found, and a wide page found elsewhere keeping the current spread zoomed (fails without the fix).ComicSpreadPostureInstrumentedTest2/2 (window-testingfold postures) — a posture change after state is saved does not crash and is applied on return.ReadiumComicOpenInstrumentedTest7/8 (single-page cases pinned to a phone-sized window).continuousRemotePageAllowsChunkedResponsesWithoutContentLengthalso fails onmainon this emulator.centerTapOpensComicChromeInTwoPageSpreadfailed once and passed on rerun.EpubSpreadActivityInstrumentedTest5/5 (no EPUB regression).Device: comic spreads are used on a Galaxy Z Fold8 from the fork build. This branch itself was run only on the emulator. Real hinge hardware with a side inset is not covered.
Peer review (Codex GPT-6-Astra), four rounds. Findings, all fixed:
Each round found new edge cases. The last round's fixes have not had a further review pass.
🤖 Generated with Claude Code