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
@@ -1,14 +1,14 @@
import Foundation
final class RDEPUBReaderLoadCoordinator {
private unowned let context: RDEPUBReaderContext
private weak var context: RDEPUBReaderContext?
init(context: RDEPUBReaderContext) {
self.context = context
}
func startInitialLoadIfNeeded() {
guard let controller = context.controller,
guard let context, let controller = context.controller,
let readerView = context.readerView,
!controller.didStartInitialLoad,
readerView.bounds.width > 0,
@@ -20,14 +20,14 @@ final class RDEPUBReaderLoadCoordinator {
}
func loadPublication() {
guard let controller = context.controller else { return }
guard let context, let controller = context.controller else { return }
context.showLoading()
let loadToken = UUID()
context.paginationToken = loadToken
DispatchQueue.global(qos: .userInitiated).async { [weak controller] in
guard let controller else { return }
let parser = self.context.makeParser()
DispatchQueue.global(qos: .userInitiated).async { [weak self] in
guard let self, let context = self.context, let controller = context.controller else { return }
let parser = context.makeParser()
do {
try parser.parse(epubURL: controller.epubURL)
@@ -37,9 +37,10 @@ final class RDEPUBReaderLoadCoordinator {
let bookmarks = controller.persistence?.loadBookmarks(for: bookIdentifier) ?? []
let highlights = controller.persistence?.loadHighlights(for: bookIdentifier) ?? []
DispatchQueue.main.async {
guard self.context.paginationToken == loadToken else { return }
self.context.runtime?.applyParsedPublication(
DispatchQueue.main.async { [weak self] in
guard let self, let context = self.context else { return }
guard context.paginationToken == loadToken else { return }
context.runtime?.applyParsedPublication(
parser: parser,
publication: publication,
bookIdentifier: bookIdentifier,
@@ -49,9 +50,10 @@ final class RDEPUBReaderLoadCoordinator {
)
}
} catch {
DispatchQueue.main.async {
guard self.context.paginationToken == loadToken else { return }
self.context.handle(error: error)
DispatchQueue.main.async { [weak self] in
guard let self, let context = self.context else { return }
guard context.paginationToken == loadToken else { return }
context.handle(error: error)
}
}
}
@@ -65,14 +67,13 @@ final class RDEPUBReaderLoadCoordinator {
bookmarks: [RDEPUBBookmark],
highlights: [RDEPUBHighlight]
) {
guard let controller = context.controller else { return }
guard let context, let controller = context.controller else { return }
context.parser = parser
context.publication = publication
context.currentBookIdentifier = bookIdentifier
context.activeBookmarks = bookmarks
context.activeHighlights = highlights
context.readingSession = RDEPUBReadingSession(publication: publication)
context.readingSession?.transition(to: .loading)
controller.title = parser.metadata.title.isEmpty
? controller.epubURL.deletingPathExtension().lastPathComponent
: parser.metadata.title