新增全书字符统计与阅读百分比,并沉淀后台渲染流水线优化方案

- 新增 RDEPUBTextStatisticsCoordinator:后台单线程按章渲染统计全书字符数,footer 显示精确阅读百分比;统计未就绪时(含 PageMap 未覆盖的 loading 页)显示"计算中",不再回退旧页码
- 统计结果按 bookID + renderSignature + 章节内容哈希做磁盘缓存,布局/字号变化自动失效;缓存命中不创建 renderer
- 移除"0.8 秒翻页时间窗轮询让路"逻辑,后续由事件驱动的交互加载门替代(见方案文档 5.6 节)
- 新增 Doc/FeatureSolution/TEXT_STATISTICS_PIPELINE_OPTIMIZATION.md:三条渲染流水线收敛为"交互 + 生产者"、交互加载门、全局后台渲染预算池、后台渲染登记表、两阶段近似百分比、自适应并发的完整优化方案与验收标准

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
shenlei
2026-07-03 18:38:41 +09:00
co-authored by Claude Fable 5
parent 71f4feb12f
commit 8b68975ee1
14 changed files with 835 additions and 14 deletions
@@ -360,7 +360,8 @@ final class RDEPUBTextContentView: UIView, UIGestureRecognizerDelegate, RDReader
chapterCFIMap: RDEPUBCFIMap? = nil,
chapterFragmentOffsets: [String: Int] = [:],
highlights: [RDEPUBHighlight] = [],
searchState: RDEPUBSearchState? = nil
searchState: RDEPUBSearchState? = nil,
footerText: String? = nil
) {
loadingSpinner.stopAnimating()
currentPage = page
@@ -378,7 +379,7 @@ final class RDEPUBTextContentView: UIView, UIGestureRecognizerDelegate, RDReader
)
backgroundColor = configuration.theme.contentBackgroundColor
pageNumberLabel.textColor = configuration.theme.contentTextColor
pageNumberLabel.text = "\(pageNumber) / \(totalPages)"
pageNumberLabel.text = footerText ?? "\(pageNumber) / \(totalPages)"
if configureCoverIfNeeded(for: page) {
#if canImport(DTCoreText)
@@ -446,7 +447,8 @@ final class RDEPUBTextContentView: UIView, UIGestureRecognizerDelegate, RDReader
func configureLoading(
pageNumber: Int,
totalPages: Int,
configuration: RDEPUBReaderConfiguration
configuration: RDEPUBReaderConfiguration,
footerText: String? = nil
) {
currentPage = nil
currentChapterCFIMap = nil
@@ -463,7 +465,7 @@ final class RDEPUBTextContentView: UIView, UIGestureRecognizerDelegate, RDReader
)
backgroundColor = configuration.theme.contentBackgroundColor
pageNumberLabel.textColor = configuration.theme.contentTextColor
pageNumberLabel.text = "\(pageNumber) / \(totalPages)"
pageNumberLabel.text = footerText ?? "\(pageNumber) / \(totalPages)"
coverImageView.isHidden = true
coverImageView.image = nil