feat: chapter runtime refactoring and related updates

- Refactor chapter runtime: replace window coordinator/snapshot with warmup orchestrator
- Update EPUB core: parser, reading session, JS bridge, navigator layout
- Update reader controller: data source, location resolution, persistence
- Update chapter runtime: data cache, loader, runtime store, disk cache, warmup orchestrator
- Remove deprecated navigation state machine and pagination state
- Update text rendering: book cache, HTML normalizer
- Update UI: text content view, dark image adjuster, text selection controller
- Update settings and reader configuration
- Add CODE_REVIEW.md and AUDIT_FINAL.md documentation
- Update pod dependencies (remove SSAlertSwift, SnapKit)
- Update podspec and pod configuration files

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
shenlei
2026-06-26 18:50:07 +09:00
co-authored by Claude
parent b8aa10c535
commit 22e7e44220
123 changed files with 3701 additions and 9118 deletions
@@ -23,7 +23,6 @@ final class RDEPUBReaderPaginationCoordinator {
}
controller.isRepaginating = true
context.runtime?.presentationRuntime.navigationStateMachine.transition(to: .repaginating)
controller.errorLabel.isHidden = true
controller.showLoading()
let token = UUID()
@@ -51,7 +50,6 @@ final class RDEPUBReaderPaginationCoordinator {
}
let paginator = context.makePaginator()
context.paginator = paginator
paginator.calculate(
parser: parser,
hostingView: controller.ensurePaginationHostView(),
@@ -63,7 +61,6 @@ final class RDEPUBReaderPaginationCoordinator {
preferences: controller.currentPreferences(),
layoutContext: controller.currentLayoutContext()
)
self.context.paginator = nil
self.context.runtime?.applyPaginationSnapshot(snapshot, restoreLocation: restoreLocation)
}
}
@@ -106,15 +103,12 @@ final class RDEPUBReaderPaginationCoordinator {
guard let controller = context.controller,
let readerView = context.readerView else { return }
controller.isRepaginating = false
context.runtime?.presentationRuntime.navigationStateMachine.transition(to: .presentingWindow)
controller.hideLoading()
readerView.reloadData()
if let targetLocation = restoreLocation {
controller.restoreReadingLocation(targetLocation)
context.readingSession?.transition(to: .idle)
} else {
readerView.transitionToPage(pageNum: 0)
context.readingSession?.transition(to: .idle)
}
context.runtime?.viewportMonitor.processPendingChangeAfterPagination()
@@ -171,10 +165,12 @@ final class RDEPUBReaderPaginationCoordinator {
let pageSize = controller.currentTextPageSize()
context.lastTextPaginationPageSize = pageSize
let layoutSnapshot = context.makeLayoutSnapshot()
let runtime = context.runtime
DispatchQueue.global(qos: .utility).async { [weak controller] in
guard controller != nil else { return }
guard context.controller != nil else { return }
guard let runtime else { return }
let prioritizedCandidates = self.prioritizedBuildableSpineIndices(
publication: publication,
readingSession: readingSession,
@@ -190,16 +186,16 @@ final class RDEPUBReaderPaginationCoordinator {
}
do {
guard context.controller != nil,
let runtime = context.runtime else { return }
let runtimeChapter = try self.loadFirstRenderableRuntimeChapter(
prioritizedSpineIndices: prioritizedCandidates,
runtime: runtime
runtime: runtime,
layoutSnapshot: layoutSnapshot
)
let initialChapters = self.loadInitialInteractiveRuntimeChapters(
anchorChapter: runtimeChapter,
publication: publication,
runtime: runtime
runtime: runtime,
layoutSnapshot: layoutSnapshot
)
DispatchQueue.main.async {
@@ -238,14 +234,16 @@ final class RDEPUBReaderPaginationCoordinator {
private func loadFirstRenderableRuntimeChapter(
prioritizedSpineIndices: [Int],
runtime: RDEPUBReaderRuntime
runtime: RDEPUBReaderRuntime,
layoutSnapshot: RDEPUBLayoutSnapshot
) throws -> RDEPUBRuntimeChapter {
var lastError: Error?
for spineIndex in prioritizedSpineIndices {
do {
return try runtime.chapterLoader.loadChapterSynchronouslyForMigration(
spineIndex: spineIndex,
store: runtime.chapterRuntimeStore
store: runtime.chapterRuntimeStore,
layoutSnapshot: layoutSnapshot
)
} catch {
lastError = error
@@ -257,7 +255,8 @@ final class RDEPUBReaderPaginationCoordinator {
private func loadInitialInteractiveRuntimeChapters(
anchorChapter: RDEPUBRuntimeChapter,
publication: RDEPUBPublication,
runtime: RDEPUBReaderRuntime
runtime: RDEPUBReaderRuntime,
layoutSnapshot: RDEPUBLayoutSnapshot
) -> [RDEPUBRuntimeChapter] {
let minimumInteractivePageCount = 2
let maximumAdditionalChapters = 1
@@ -283,10 +282,14 @@ final class RDEPUBReaderPaginationCoordinator {
do {
let chapter = try runtime.chapterLoader.loadChapterSynchronouslyForMigration(
spineIndex: spineIndex,
store: runtime.chapterRuntimeStore
store: runtime.chapterRuntimeStore,
layoutSnapshot: layoutSnapshot
)
selectedChapters.append(chapter)
} catch {
#if DEBUG
print("[RDEPUBReaderPaginationCoordinator] ⚠️ Failed to load chapter at spineIndex \(spineIndex): \(error)")
#endif
}
}