Repository navigation
feat: two-page EPUB spreads on unfolded foldables and landscape tablets (refs #286) - #300
Merged
Merged
Conversation
Add a geometry-based spread policy (sw>=600dp, horizontal, paginated, not tabletop) backed by Jetpack WindowManager posture, per-library spread preferences with options UI, and Readium two-column/fixed-layout spread configuration that bypasses ReadiumCSS's 60em media query. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Each spread page now gets the same margin on its outer and inner side, sized like the single-page margin for the same setting, and changes to margins apply live. The container drops its horizontal padding in a spread; Readium's per-column gutter is a 1px unit scaled by pageMargins. Tests: JVM margin mapping; on-device measurement of all four page margins, line pitch on both pages under line-spacing and font-size changes, and the rotate-to-portrait fallback for EPUB and comics. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ed; EPUB-only scope - ReaderWindowTracker.observeSpreadChanges collects spread decisions under repeatOnLifecycle(STARTED) and re-checks on each start, so a debounced posture change cannot recreate the activity after state is saved and a change made while hidden is applied on return. - Drop comic-only spread settings from this change; comic spreads are a separate PR. - EpubSpreadActivityInstrumentedTest: two columns vs one, setting off, symmetric margins following the margin setting, line spacing and font size on both pages, rotate-to-portrait fallback. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- The spread page margin is capped at an eighth of the window, so each page keeps at least half its width for text at the largest margin settings instead of collapsing to nothing. - Fixed-layout spreads are drawn by Readium and do not use the reflowable column padding, so they keep the normal container margins. - EpubSpreadWebViewInstrumentedTest checks the column properties against the shipped ReadiumCSS below its 60em breakpoint. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The hinge gutter helper is used only by comic spreads and moves to that change; the unused window-testing dependency is dropped. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
4 tasks done
Owner
|
Thanks @chortya, this looks good. The EPUB spread behavior is covered by the new tests, CI is passing, and I found no further changes needed. The PR is ready to merge. |
This was referenced Oct 21, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Contribution pause
The maintainer lifted the pause and invited split PRs in #286.
Summary
On an unfolded foldable (e.g. Galaxy Z Fold) or a landscape tablet, paginated EPUB shows two pages side by side, like a printed book. Portrait, the folded cover screen, split-screen and continuous layout stay single-page.
ReaderSpreadPolicyReaderWindowTrackerFoldingFeatureposture, debounced; collected only while the reader is started, re-checked on each start.columnCount = TWO/ fixed-layoutSpread.ALWAYS, plus inlineRsProperties(--RS__colCount: 2,--RS__colWidth: auto,--RS__pageGutter). The inline properties bypass ReadiumCSS's 60em two-column media query, which Fold inner displays do not reach.submitPreferences. Fixed-layout spreads keep the normal container margins.Two-page spread when unfolded, per library, on by default, in the reader options (EPUB layout section) and the library reader settings. Stored with the existing library reader profile; older profiles default to on.New dependencies:
androidx.window:windowandwindow-java1.5.1.Verification
./gradlew :app:testDebugUnitTest— 971/971 pass (new:ReaderSpreadPolicyTest,EpubSpreadPreferencesTest, spread cases inLibraryReaderPreferencesTest).:app:lintDebug— 0 errors.:app:assembleDebugsucceeds. No added trailing whitespace; line endings preserved.EpubSpreadActivityInstrumentedTest5/5 — two columns on the unfolded window and one otherwise, setting off keeps one column, all four page margins equal and following 15% / 40% / uneven / 100% (capped) settings live, line spacing and font size identical on both pages, rotate to portrait returns to one column.EpubSpreadWebViewInstrumentedTest2/2 — the column properties against the shipped ReadiumCSS below 60em.ReadiumEpubOpenInstrumentedTest20/22 (new spread preference cases pass). The 2 failures (selectsARealReadiumPositionForNonzeroServerPercentage,generatedEpubImageColorOverrideIsUniversalAndIdempotent) also fail onmainon this emulator.centerTapOpensLightweightReaderChromefailed once and passed on rerun.EpubReaderOptionsOverlayInstrumentedTest3/8; the same 5 fail onmainon this emulator.Spread.ALWAYS), posture changes on real hinge hardware.readiumEpubReadingProgressionmaps both library reading directions to ReadiumLTR(pinned by an existingLibraryReaderPreferencesTest), and Readium 3.0.2 enables vertical text only for a CJK language and RTL progression, so vertical text cannot occur in this app today. If RTL progression is ever passed through, the spread should be gated on Readium's resolvedverticalText.🤖 Generated with Claude Code