Skip to content

feat(mobile): 朗讀跟讀底線標記、精確頁尾自動翻頁與朗讀控制列#7

Merged
Retsomm merged 2 commits into
mainfrom
dev
Jul 6, 2026
Merged

feat(mobile): 朗讀跟讀底線標記、精確頁尾自動翻頁與朗讀控制列#7
Retsomm merged 2 commits into
mainfrom
dev

Conversation

@Retsomm

@Retsomm Retsomm commented Jul 5, 2026

Copy link
Copy Markdown
Owner
  • reader-web 新增 ttsBoundary 訊息,依 expo-speech onBoundary 的絕對字元位移, 在朗讀中的句子下方畫底線標記,並在快讀到頁尾時自動翻頁(不用等整章念完)
  • 修正 tts.ts 暫停後恢復播放會整段重講的問題,改成從暫停時的絕對位移接續朗讀
  • 修正 iOS 睡眠計時在背景被系統節流時,超過設定時間仍繼續播放的問題
  • 新增閱讀頁朗讀控制列(播放/暫停、重置、睡眠計時循環切換),置於內容與頁碼列 之間、固定高度渲染,避免遮住內容或觸發 WebView 重新分頁

Summary by CodeRabbit

  • New Features

    • Improved text-to-speech synchronization with reader text highlighting, including accurate boundary alignment and auto-follow.
    • Added a new sleep-timer icon to support the updated TTS controls.
  • Bug Fixes

    • Reduced repeated page/turn loops during chapter auto-advance and improved end-of-book handling.
    • Reworked pause/resume/reset behavior to reliably stop playback and continue from the correct position.
    • Made sleep timer expiration more reliable when backgrounded and resumed.
  • UI/Behavior

    • Updated TTS control bar logic for clearer play/pause/reset states.

- reader-web 新增 ttsBoundary 訊息,依 expo-speech onBoundary 的絕對字元位移,
  在朗讀中的句子下方畫底線標記,並在快讀到頁尾時自動翻頁(不用等整章念完)
- 修正 tts.ts 暫停後恢復播放會整段重講的問題,改成從暫停時的絕對位移接續朗讀
- 修正 iOS 睡眠計時在背景被系統節流時,超過設定時間仍繼續播放的問題
- 新增閱讀頁朗讀控制列(播放/暫停、重置、睡眠計時循環切換),置於內容與頁碼列
  之間、固定高度渲染,避免遮住內容或觸發 WebView 重新分頁

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Jul 5, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
travel-in-time Ready Ready Preview, Comment Jul 6, 2026 12:48am

@coderabbitai

coderabbitai Bot commented Jul 5, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: f9516612-1def-45d8-b004-027a3b112050

📥 Commits

Reviewing files that changed from the base of the PR and between 5872fc9 and 2e33f8b.

📒 Files selected for processing (4)
  • mobile/lib/readerHtml.generated.ts
  • mobile/lib/tts.ts
  • mobile/reader-web/index.ts
  • mobile/reader-web/ttsHighlight.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • mobile/reader-web/index.ts
  • mobile/reader-web/ttsHighlight.ts
  • mobile/lib/tts.ts

📝 Walkthrough

Walkthrough

This PR adds synchronized text-to-speech for the mobile reader by extending TTS messages, adding absolute-offset speech resume and deadline-based sleep timing, introducing WebView text indexing and highlight rendering, wiring boundary-driven page follow, and updating the reader screen controls and chapter-advance flow.

Changes

Reader TTS feature

Layer / File(s) Summary
TTS message contract and hook timing
mobile/lib/readerMessages.ts, mobile/lib/tts.ts
Extends InboundMessage with ttsStart/ttsBoundary/ttsStop, and updates useTTS with boundary callbacks, chunk-offset resume, and deadline-based sleep handling.
TTS text indexing and highlights
mobile/reader-web/ttsHighlight.ts
Adds cached DOM text indexing, offset/range conversion, CSS Custom Highlight styling, overlay fallback painting, and cleanup helpers.
WebView TTS tracking and auto-follow
mobile/reader-web/index.ts
Wires TTS start/boundary/stop messages, tracks the visible document, paints highlights, advances pages near the end of a range, and refreshes text-index state on relocation and content mutation.
Native reader TTS controls and chapter advance
mobile/app/reader/[id].tsx, mobile/components/icons.tsx
Reworks reader-screen TTS playback and chapter advancement, updates pause/reset wiring, rebuilds the control bar, and adds the sleep-timer icon.

Estimated code review effort: 4 (Complex) | ~60 minutes

Possibly related PRs

  • Retsomm/TravelInTime#3: Modifies the same reader WebView and native TTS wiring surfaces used here, including chapter-text retrieval and message handling.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main mobile TTS highlight, auto-page-turn, and control-bar changes.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch dev

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
mobile/lib/tts.ts (1)

250-253: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Sleep timer should not restart on every chapter
readNextAndContinue() calls tts.speak() for each auto-advanced chapter, so startSleepTimer(sleepMinutes) resets the deadline every time and the timer can never expire during continuous reading. Only start it when no deadline is already running.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@mobile/lib/tts.ts` around lines 250 - 253, In readNextAndContinue()’s speak
flow, the sleep timer is being restarted on every auto-advanced chapter because
startSleepTimer(sleepMinutes) is called whenever sleepMinutes > 0. Update the
logic around speakChunk(generation) so the timer only starts if no active
deadline is already running, and keep the existing sleepMinutes check in
tts.speak() or its caller to avoid resetting the countdown during continuous
reading.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@mobile/reader-web/ttsHighlight.ts`:
- Around line 55-81: The TTS text index cache can become stale after
`applyScriptToDoc()` changes text via `convertDoc()`/`restoreDoc()`, so offsets
returned by `getTextIndex()` may no longer match the document. Update the
script/typography change flow to invalidate `ttsTextIndexCache` for the affected
document whenever text is rewritten, and ensure `getTextIndex()` rebuilds the
index from the current `Text.nodeValue` values after those conversions.

---

Outside diff comments:
In `@mobile/lib/tts.ts`:
- Around line 250-253: In readNextAndContinue()’s speak flow, the sleep timer is
being restarted on every auto-advanced chapter because
startSleepTimer(sleepMinutes) is called whenever sleepMinutes > 0. Update the
logic around speakChunk(generation) so the timer only starts if no active
deadline is already running, and keep the existing sleepMinutes check in
tts.speak() or its caller to avoid resetting the countdown during continuous
reading.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: bf9ab482-b10a-4d46-bbdd-0c806d801773

📥 Commits

Reviewing files that changed from the base of the PR and between 2b002f1 and 5872fc9.

📒 Files selected for processing (7)
  • mobile/app/reader/[id].tsx
  • mobile/components/icons.tsx
  • mobile/lib/readerHtml.generated.ts
  • mobile/lib/readerMessages.ts
  • mobile/lib/tts.ts
  • mobile/reader-web/index.ts
  • mobile/reader-web/ttsHighlight.ts

Comment thread mobile/reader-web/ttsHighlight.ts
- ttsHighlight.ts: 新增 invalidateTextIndex(),簡繁轉換改寫 nodeValue 後清掉
  getTextIndex 的快取,避免朗讀抓到轉換前的舊文字
- tts.ts: speak() 只在沒有睡眠計時 deadline 在跑時才啟動計時器,避免跨章節
  自動接續朗讀時倒數被每一章重置

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@Retsomm Retsomm merged commit 9fb9726 into main Jul 6, 2026
6 checks passed
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