Repository navigation
fix: keep EPUB reading position after read-aloud (refs #286) - #296
Conversation
Background read-aloud saves each utterance position after the reader stopped. Two paths then put the reader back at the older visual page and saved it over the newer position (and reported it to the server): - Rebuilding the reader from saved instance state (process death) preferred the saved-state locator over the newer stored position. The stores, written on every move, now win; saved state is only a fallback (preview). - Returning to the foreground replayed the navigator's last position through the locator flow and the pagination listener. Only real moves are recorded now; re-reports of the same place are written only while the store still holds this reader's own position. Also send the current read-aloud position to the server when playback is paused, past the 15 s / 0.2% progress throttle. Tests: instrumented regression tests for both paths (red before the fix) and for configuration recreation. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
After recreation (rotation, fold, process death) the reader followed the saved read-aloud position even with no read-aloud session running. That position is where listening last stopped, often far behind where the book was read since, and the jump was then saved and synced. Only a live session for this reader is followed now; the saved position remains the Keep listening start point. Test: instrumented regression (red before the fix). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@chortya Thanks for the focused fix and for adding thorough regression tests. The changes clearly target the reported issue, and the coverage for saved-state restoration and returning to the reader is valuable. One edge case remains: When the reader is backgrounded, read-aloud can save a newer position in the background. When the reader returns to the foreground, Readium may re-paginate and report the previous visual page again, but with slightly different progression, fragment, or position details. In that case, Please add a regression test for this scenario or adjust the protection so a stale visual callback cannot replace newer read-aloud progress. Other than this edge case, the PR looks good. Once this is addressed, it will be merged. |
…aloud progress Returning to the foreground, Readium can re-report the page the reader showed before with slightly different progression, fragment or position details, which counted as a move and overwrote the position background read-aloud saved meanwhile. When the stored position is not the one this reader wrote, the reader now goes to it and ignores visual reports that are not nearer it than the old page until it arrives (at most 5 s). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Only reports that look like the stale page are skipped (its resource when read-aloud moved on to another one, or nearer the stale page than the newer position). Explicit navigation ends the catch-up, and when the window passes the navigator's current position is recorded unless it is still the stale page. The regression tests inject reports while the catch-up is demonstrably pending. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… the reader Tap-zone navigation is a deliberate move and ends the catch-up like the other navigation paths. When the window passes, the navigator's current position is recorded as is: any re-pagination replay is over by then, so a swipe made meanwhile is not lost. The tests hold the catch-up navigation behind a barrier, so the replayed report and the arrival are delivered in a fixed order. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A catch-up still pending when the reader is stopped again could time out in the background and record the stale visual page over newer read-aloud progress. Stopping ends it; the next start catches up afresh. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The directional navigation adapter reports the start of a drag as a deliberate move (without consuming it), so a swipe made while catching up is recorded instead of waiting for the timeout. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Thanks! Addressed in the new commits on this branch. Fix. When the reader returns to the foreground and the stored position is no longer the one it wrote, background read-aloud has moved on. The reader then:
Regression tests (
|
|
Thanks @chortya, this looks good now. The remaining read-aloud position issue is covered, and the added tests address the edge cases we discussed. No further changes needed from me. This is ready to merge. |
Contribution pause
Maintainer-requested exception
Summary
Refs #286. Fixes EPUB reading positions jumping back after read-aloud (TTS) was used. Builds on #277: its server-vs-local choice on open is unchanged, and its stale-narration cleanup still runs on every real move.
While the reader is in the background,
EpubTtsPlaybackServicekeeps saving each utterance toReadiumEpubLocatorStore, so the stored position moves on afteronSaveInstanceStatehas captured the reader's state. Three paths then put the reader back at an older position, saved it, and reported it to the server:requestedLocator, the locator from the saved instance state, won over the newer stored position. NowepubRestoredLocatorprefers the stored position, since the stores are written on every move. Saved state is only the fallback, for preview, which never writes the store. The same applies to the saved TTS locator.repeatOnLifecycle(STARTED)re-collectscurrentLocator, andPaginationListener.onPageChangedre-fires after resume. Both replayed the last visual position over the newer read-aloud position. Both now go throughrecordVisualLocator. Real moves are recorded as before. A re-report of the same place, including the later report enriched withposition/totalProgression, is written only while the store still holds this reader's own last position.restoreTtsPositionAfterRecreationfell back to the saved TTS locator even with no TTS session running. After rotation, fold or process death, the reader jumped to where listening last stopped, which can be far behind where the book has been read since. It now follows only a live session for this reader (hasSession). The saved TTS position remains the Keep listening start point.Also, pausing read-aloud sends the current position to the server straight away. Previously the 15 s / 0.2% throttle could leave the last stretch unsent if the app was killed while paused.
Verification
./gradlew :app:testDebugUnitTest— 946/946 pass.:app:lintDebug— 0 errors.:app:compileDebugAndroidTestKotlinand:app:assembleDebugsucceed.git diff --checkis clean.EpubPositionRestoreInstrumentedTest(6 tests) on a Pixel Fold API 36 emulator. The three bug tests fail on currentmainand pass with this change, in two consecutive runs. The others cover normal rotation and the two helpers. The rebuild test records every position written, because onmainthe jump to the old read-aloud position is sometimes overwritten again moments later.ReadiumEpubOpenInstrumentedTest(17) andEpubReaderProgressFooterInstrumentedTest(1) pass, exceptselectsARealReadiumPositionForNonzeroServerPercentageandgeneratedEpubImageColorOverrideIsUniversalAndIdempotent, which fail the same way on unmodifiedmainon this emulator.