Phase 1: Context 拆分 - 新增 RDEPUBReaderState/RDEPUBReaderEnvironment/RDEPUBReaderServices - RDEPUBReaderContext 改为过渡门面,代理到 State/Environment/Services Phase 2: Runtime 拆分 - 新增 RDEPUBPresentationRuntime 处理分页状态管理 - 新增 RDEPUBChapterWarmupOrchestrator 处理章节预热与加载编排 - RDEPUBReaderRuntime 从 1277 行收缩,公共 API 转发到新 facade Phase 0.5: 性能优化 - prepareOnDemandChapter 支持异步模式(allowSynchronousLoad: false) - extendPartialBookPageMapIfNeeded 改为 DispatchGroup 并发加载 - RDEPUBChapterOffsetMap.cfiMap 加 NSLock 保护数据竞争 - CFI Map 构建延迟到后台队列(scheduleDeferredCFIMapBuildIfNeeded) - RDEPUBTextPageRenderView 引入静态位图缓存 - RDEPUBTextContentView 新增 loadingSpinner 占位页 Phase 3: 状态机 - 新增 RDEPUBNavigationStateMachine(含 DEBUG 合法转换校验) - 新增 RDEPUBPaginationState 记录分页来源 Review 修复 - makeSummary 重复方法合并 - ensureNavigationTargetAvailable 同步路径加注释标记 UI 测试 - 新增 AsyncChapterLoadingTests(20 个测试,覆盖全部架构整改场景) - 跨章节翻页、延迟 CFI、状态机、内存警告、预加载、位置恢复等
73 lines
2.6 KiB
Swift
73 lines
2.6 KiB
Swift
import UIKit
|
|
|
|
final class RDEPUBReaderEnvironment {
|
|
|
|
weak var controller: RDEPUBReaderController?
|
|
|
|
weak var readerView: RDReaderView?
|
|
|
|
var displayEnvironment: any RDEPUBReaderDisplayEnvironment
|
|
|
|
init(
|
|
controller: RDEPUBReaderController,
|
|
readerView: RDReaderView,
|
|
displayEnvironment: any RDEPUBReaderDisplayEnvironment
|
|
) {
|
|
self.controller = controller
|
|
self.readerView = readerView
|
|
self.displayEnvironment = displayEnvironment
|
|
}
|
|
|
|
func currentLayoutContext(configuration: RDEPUBReaderConfiguration) -> RDEPUBNavigatorLayoutContext {
|
|
let containerSize = readerView?.bounds.size ?? .zero
|
|
let viewSize = controller?.view.bounds.size ?? containerSize
|
|
let resolvedSize = containerSize == .zero ? viewSize : containerSize
|
|
return RDEPUBNavigatorLayoutContext(
|
|
containerSize: resolvedSize,
|
|
pagesPerScreen: readerView?.pagesPerScreen ?? 1,
|
|
safeAreaInsets: controller?.view.safeAreaInsets ?? .zero,
|
|
userInterfaceIdiom: controller?.traitCollection.userInterfaceIdiom ?? .phone,
|
|
reflowableContentInsets: configuration.reflowableContentInsets
|
|
)
|
|
}
|
|
|
|
func currentTextRenderStyle(configuration: RDEPUBReaderConfiguration) -> RDEPUBTextRenderStyle {
|
|
let font = configuration.fontChoice.font(ofSize: configuration.fontSize)
|
|
let lineSpacing = max(font.lineHeight * (configuration.lineHeightMultiple - 1), 4)
|
|
return RDEPUBTextRenderStyle(
|
|
font: font,
|
|
lineSpacing: lineSpacing,
|
|
textColor: configuration.theme.contentTextColor,
|
|
backgroundColor: configuration.theme.contentBackgroundColor
|
|
)
|
|
}
|
|
|
|
func currentTextLayoutConfig(
|
|
configuration: RDEPUBReaderConfiguration,
|
|
pageSize: CGSize
|
|
) -> RDEPUBTextLayoutConfig {
|
|
RDEPUBTextLayoutConfig(
|
|
frameWidth: max(pageSize.width, 1),
|
|
frameHeight: max(pageSize.height, 1),
|
|
edgeInsets: configuration.reflowableContentInsets,
|
|
numberOfColumns: configuration.numberOfColumns,
|
|
columnGap: configuration.columnGap,
|
|
avoidOrphans: false,
|
|
avoidWidows: false,
|
|
avoidPageBreakInsideEnabled: true,
|
|
hyphenation: true,
|
|
imageMaxHeightRatio: 0.85,
|
|
fallbackViewportSize: displayEnvironment.fallbackViewportSize
|
|
)
|
|
}
|
|
|
|
var currentBrightness: CGFloat {
|
|
get { displayEnvironment.currentBrightness }
|
|
set { displayEnvironment.currentBrightness = newValue }
|
|
}
|
|
|
|
var fallbackViewportSize: CGSize {
|
|
displayEnvironment.fallbackViewportSize
|
|
}
|
|
}
|