Skip to content

fix(ios): prevent MO paragraph column-breaks for audio/visual sync#160

Draft
ddfreiling wants to merge 3 commits into
Notalib:mainfrom
ddfreiling:fix/mo-column-breaks
Draft

fix(ios): prevent MO paragraph column-breaks for audio/visual sync#160
ddfreiling wants to merge 3 commits into
Notalib:mainfrom
ddfreiling:fix/mo-column-breaks

Conversation

@ddfreiling

Copy link
Copy Markdown
Member

In paginated CSS-column layout, a paragraph straddling two columns would play its full audio while the reader stayed pinned to column 1, leaving the column-2 continuation invisible. When media-overlay playback starts, inject p { break-inside: avoid !important; } so each paragraph stays whole on one page, keeping audio and visible text in sync.

Exposed as EPUBPreferences.preventMOColumnBreaks (default true) so consumers can opt out if they prefer the original layout. Re-evaluated whenever preferences are updated mid-session. The ReadiumReaderView protocol gains setMOActive(_:) to separate the "MO is active" signal from the CSS-injection decision, which lives entirely in EPUBReaderView.

ddfreiling and others added 2 commits June 23, 2026 16:40
In paginated CSS-column layout, a paragraph straddling two columns would
play its full audio while the reader stayed pinned to column 1, leaving
the column-2 continuation invisible. When media-overlay playback starts,
inject `p { break-inside: avoid !important; }` so each paragraph stays
whole on one page, keeping audio and visible text in sync.

Exposed as `EPUBPreferences.preventMOColumnBreaks` (default `true`) so
consumers can opt out if they prefer the original layout. Re-evaluated
whenever preferences are updated mid-session. The `ReadiumReaderView`
protocol gains `setMOActive(_:)` to separate the "MO is active" signal
from the CSS-injection decision, which lives entirely in EPUBReaderView.

Also adds `.npmrc` to the helper-scripts package to suppress
`min-release-age` for the git-sourced `readium-css` dependency, which
caused `npm install` to fail when a global `min-release-age` was set.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… sync

Extends the iOS fix to Android and Web. When media-overlay playback starts,
injectMOBreakCSS() / removeMOBreakCSS() are called via the shared
window.flutterReadium helper-script bundle (FlutterReadiumTools.ts) so
the CSS lives in one place and each platform only calls one-line JS.

- Android: inject on MO start, remove on stop, re-inject on spine-item
  change (onPageChanged), and re-evaluate when preferences change mid-session.
- Web: inject on audioEnable (MO path), remove on stop, re-inject in the
  frameLoaded callback (via onFrameLoaded hook in FlutterEpubNavigator), and
  re-evaluate when setEPUBPreferences is called mid-session.
- Helper scripts: adds injectMOBreakCSS() and removeMOBreakCSS() to
  FlutterReadiumTools; rebuilds the rollup bundle.
- Dart: preventMOColumnBreaks field already present from iOS commit; Android
  also wires it in FlutterEpubPreferences.kt.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@ddfreiling ddfreiling force-pushed the fix/mo-column-breaks branch from 90213c3 to 34bc849 Compare June 23, 2026 15:01
Bypass window.flutterReadium for CSS injection on web. The helper
script initialises window.flutterReadium inside requestAnimationFrame,
so it doesn't exist yet when frameLoaded fires synchronously. Direct
DOM manipulation is race-free and makes the rAF timing irrelevant.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
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