| tags |
|
|---|
依循 functional-thinking.md.md 的 Grokking Simplicity 原則(action / calculation / data 分層),依序重構 PWA、RENDERER、RN 三個版本。
- ✅ PWA(
pwa/)— 已完成 - ✅ RENDERER(
renderer/)— 已完成 - 🔶 RN / mobile(
mobile/)— 程式碼搬移完成,待使用者實機測試
每完成一個版本先暫停,等使用者確認沒問題再進行下一個。
目標檔案:pwa/src/page/Reader.tsx(原始 2383 行,混雜計算邏輯與副作用)
- 新增 4 個純計算檔案(
pwa/src/components/Reader/),逐字搬移邏輯,零行為改動:progressCalculations.ts— 頁碼/總頁數換算tocLookup.ts— TOC / spine 章節查找ttsFollowCalculations.ts— TTS 翻頁判斷邏輯bookmarkUtils.ts— 書籤資料操作
- 抽出
useBookmarks.ts(pwa/src/hooks/reader/) - 抽出
useAnnotationPopups.ts(pwa/src/hooks/reader/) - 抽出
useChapterPageScan.ts(pwa/src/hooks/reader/) - 合併 book 生命週期與 TTS 跟讀邏輯為
useReaderEngine.ts(pwa/src/hooks/reader/)- 原規劃拆成
useEpubBook+useTTSFollow兩個獨立檔案,但發現兩者實際雙向耦合(relocated事件直接呼叫 TTS 函數,TTS 又依賴 book 初始化建立的 refs),經與使用者確認後改為合併成單一 hook
- 原規劃拆成
-
Reader.tsx從 2383 行降至 641 行,現在主要是 refs/hooks 組裝 + JSX render - 每個階段皆執行
cd pwa && yarn build驗證型別/編譯無誤
- 翻頁(含 RTL 模式)
- 朗讀播放 / 暫停 / 繼續 / 跨章節自動翻頁
- 選字高亮 popup(新增/編輯/刪除標記)
- 書籤新增 / 刪除 / 跳轉
- 簡繁轉換
- 深色模式
- 字體大小 / 字型 / 行距 / 字距設定
- 睡眠計時器
- 手機版 Safari(過去有 iOS 專屬的 selectionchange / 觸控 bug,本次確認正常)
PWA 重構已通過完整實測,可視為此階段完成。
目標檔案:renderer/src/page/Reader.tsx(原始 1850 行,重構後 314 行)
更正:舊版本文件寫「renderer 少了書籤功能」已過期——renderer 其實已有完整書籤功能與更早就元件化的 BookmarkPanel.tsx / HighlightPopup.tsx,只是書籤/annotation/TTS 邏輯尚未抽成純函數 + hooks。
- 新增 4 個純計算檔案(
renderer/src/components/Reader/,與 pwa 共用同一份邏輯,逐字搬移):progressCalculations.ts、tocLookup.ts、bookmarkUtils.ts、ttsFollowCalculations.ts
- 抽出
useBookmarks.ts、useChapterPageScan.ts、useAnnotationPopups.ts、useReaderEngine.ts(renderer/src/hooks/reader/)useAnnotationPopups.ts依 renderer 現有HighlightPopup.tsx介面調整為{x, y}座標(不採用 pwa 版的{left, top}clamp 寫法)useReaderEngine.ts以 renderer 原有邏輯為底重新組織(而非直接搬 pwa 版),刻意保留 renderer 特有行為:- TTS 高亮改用 renderer 原有的 CSS Custom Highlight API 直接繪製(不採用 pwa 版新增的 DOM overlay fallback,那是獨立的行為改動,超出本次重構範圍)
- 不引入 pwa 版新增的行動裝置專屬邏輯(觸控 selectionchange 選字路徑、iOS selectionchange 轉發、
getVisibleContentDocument多 iframe 命中測試)——Electron 桌面版不需要
- 同步修正
renderer/src/store/useAnnotationStore.ts的addAnnotation,改為回傳新建立的 id(比照 pwa 版介面,讓useAnnotationPopups.ts可直接使用回傳值) - 修掉章節掃描 bug:背景掃描改用獨立的
ePub(buffer.slice(0))實例(useChapterPageScan.ts),不再複用主book建立第二個 rendition,避免掃描完成時偶爾清空主渲染器 annotation 的問題
-
Reader.tsx從 1850 行降至 314 行 -
cd renderer && yarn build驗證型別/編譯無誤
- 翻頁、鍵盤左右鍵翻頁
- 朗讀播放/暫停/繼續/跨章節自動翻頁
- 選字高亮 popup 位置(新增/編輯/刪除標記)
- 書籤新增/刪除/跳轉
- 簡繁轉換、深色模式、字體大小/字型/行距/字距設定
- 睡眠計時器
- 章節掃描:切換字體大小後多次翻頁,頁碼校正正確且高亮標記不會被意外清除
- 朗讀跟隨螢光色閃爍、同時出現在目標與非目標句子:
renderer/src/hooks/useTTS.ts仍保留舊版「估算進度計時器」(每 250ms 用預估字速推進高亮位置),與真實onboundary事件互相搶跑造成閃爍。比照 pwa 版已驗證過的修法,移除估算計時器,高亮改成只跟隨真實 boundary 事件。 - 註記跳轉後不顯示:在
useReaderEngine.ts的relocated事件中新增補救邏輯——每次換頁/跳轉後延遲檢查當前章節的既有註記是否有對應 SVG 底線,缺漏則重新呼叫addEpubAnnotation補畫(epub.js 的annotations.inject(view)在 contents 尚未完全就緒時偶爾會失敗)。 - 書庫排序按鈕(最近閱讀/書名/進度)點擊無效:與本次 Reader 重構無關的既有 bug——
Library.tsx外層有drag-region(Electron 視窗可拖曳區域),SortControl.tsx的按鈕缺少no-dragclass,導致點擊被系統拖曳行為吃掉。已補上no-drag。
RENDERER 重構已通過完整實測,可視為此階段完成。
目標目錄:mobile/(Expo Router + react-native-webview + epub.js,是兩個獨立的 JS 世界:
RN 端負責畫面與 AsyncStorage,WebView 端獨立打包一份 epub.js reader 邏輯)。
RN 端(mobile/app/reader/[id].tsx 從 788 行降至 383 行):
- 新增
mobile/lib/reader/calculations.ts:書籤/註記陣列運算、睡眠計時循環選項、 URL scheme 判斷、頁碼百分比格式化,以及從lib/tts.ts搬過來的splitTextByLength/withFriendlyLabels/dedupeByLanguage(純函數,逐字搬移零行為改動) - 抽出
mobile/hooks/reader/useReaderEngine.ts(WebView 訊息橋接、relocated/toc/選字狀態、 排版設定載入存檔)、useBookmarks.ts、useAnnotations.ts、useTTSReading.ts(朗讀跨章節跟讀) -
mobile/lib/library.ts不動(書庫列表與 Reader 共用資料層,不在本次重構範圍)
WebView 端(mobile/reader-web/index.ts 從 1132 行降至 692 行):
- 新增
tocLookup.ts(TOC 查找)、progressCalculations.ts(頁碼/百分比換算純函數)、ttsFollowCalculations.ts(朗讀跟讀「是否該自動翻頁」純判斷)、scriptConversion.ts(簡繁轉換)、readerStyles.ts(排版/深色模式 DOM 樣式注入)、annotationUtils.ts(標記差異比對純函數diffAnnotations+ DOM 操作) -
index.ts保留 module 狀態、book/rendition 生命週期、handleMessagedispatcher, 改為呼叫上述新模組
-
cd mobile && npx tsc --noEmit型別檢查通過 -
yarn build:reader成功打包(esbuild 不做型別檢查,只驗證語法/bundle 成功) - 使用者實機/模擬器測試(尚未進行,我無法在此環境驗證 RN/WebView 執行期行為):
- 翻頁(含 RTL、tap-zone 點擊)
- 朗讀播放/暫停/繼續/跨章節自動翻頁跟讀
- 選字劃線(含劃線模式切換)/ 標記顏色編輯 / 刪除 / 筆記
- 書籤新增/刪除/跳轉
- 簡繁轉換(含書本原始語言偵測 baseScript)
- 深色模式
- 字體大小/字型/行距/字距設定
- 睡眠計時
- 章節背景掃描完成後頁碼校正正確
在使用者完成上述實機測試並回報無誤前,此階段不可視為完成。
- 重構指導原則:functional-thinking.md.md