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
@@ -26,7 +26,7 @@ final class RDEPUBMetadataParseWorker {
private let backgroundInteractionCooldown: CFAbsoluteTime = 0.8
unowned let context: RDEPUBReaderContext
weak var context: RDEPUBReaderContext?
let cancellationController: RDEPUBMetadataParseCancellationController
@@ -114,12 +114,16 @@ final class RDEPUBMetadataParseWorker {
}
func start(token: UUID, restoreLocation: RDEPUBLocation?) {
let context = self.context
let cancellationController = self.cancellationController
DispatchQueue.global(qos: .utility).async { [weak self] in
guard let self else { return }
defer { self.context.runtime?.paginationCoordinator.finishMetadataParseCancellationController(cancellationController) }
let context = self.context
guard let context,
context.controller != nil,
!cancellationController.isCancelled,
context.paginationToken == token else { return }
defer { context.runtime?.paginationCoordinator.finishMetadataParseCancellationController(cancellationController) }
guard context.controller != nil,
!cancellationController.isCancelled,
context.paginationToken == token else { return }
@@ -382,10 +386,16 @@ final class RDEPUBMetadataParseWorker {
private func waitForReadingInteractionToSettle(
cancellationController: RDEPUBMetadataParseCancellationController? = nil
) {
while context.controller != nil,
let semaphore = DispatchSemaphore(value: 0)
let maxWaitIterations = 100 // ~8 seconds max wait
var iteration = 0
while context?.controller != nil,
cancellationController?.isCancelled != true,
context.secondsSinceLastUserNavigation() < backgroundInteractionCooldown {
Thread.sleep(forTimeInterval: 0.08)
iteration < maxWaitIterations {
let elapsed = context?.secondsSinceLastUserNavigation() ?? 0
if elapsed >= backgroundInteractionCooldown { break }
semaphore.wait(timeout: .now() + 0.08)
iteration += 1
}
}
@@ -403,8 +413,7 @@ final class RDEPUBMetadataParseWorker {
let delay = Self.retryDelays[min(retryCount, Self.retryDelays.count - 1)]
DispatchQueue.global(qos: .utility).asyncAfter(deadline: .now() + delay) { [weak self] in
guard let self else { return }
let context = self.context
guard let self, let context = self.context else { return }
guard context.controller != nil,
context.paginationToken == self.token,
!cancellationController.isCancelled else {