- 新增 RDEPUBResourceDataProvider 解密钩子协议 + 访问登记表,收敛章节 HTML/ 图片/内联 CSS/脚注/封面/图片查看器/正文取图等读取点,scheme handler 对加密书 禁用流式分支;新增 RDEPUBDecryptingImageAttachment 解密 DTCoreText 图片附件; RDEPUBReaderDependencies.live(resourceDataProvider:) 便捷注入。明文书零影响。 - 试读墙:configuration.trialPolicy + delegate epubReaderTrialWallView/ DidReachTrialWall,UI 由宿主提供(RDEPUBReaderController+Trial)。 - 工具栏定制:RDEPUBReaderTop/BottomToolViewProtocol 协议 + dependencies 工厂注入, 内置栏已 conform,configureTopToolView 改协议类型。 - 朝向锁定:RDEPUBMetadata.orientation(OPF rendition:orientation 主, iBooks display-options 兜底)+ RDEPUBReaderController+Orientation 重写支持朝向、 打开后主动转向。 注:RDEPUBReaderController+LocationResolution / PaginationCoordinator 为本次改动前 即存在的工作区修改,一并纳入。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
87 lines
3.5 KiB
Swift
87 lines
3.5 KiB
Swift
import Foundation
|
|
|
|
final class RDEPUBReaderLoadCoordinator {
|
|
private weak var context: RDEPUBReaderContext?
|
|
|
|
init(context: RDEPUBReaderContext) {
|
|
self.context = context
|
|
}
|
|
|
|
func startInitialLoadIfNeeded() {
|
|
guard let context, let controller = context.controller,
|
|
let readerView = context.readerView,
|
|
!controller.didStartInitialLoad,
|
|
readerView.bounds.width > 0,
|
|
readerView.bounds.height > 0 else {
|
|
return
|
|
}
|
|
controller.didStartInitialLoad = true
|
|
loadPublication()
|
|
}
|
|
|
|
func loadPublication() {
|
|
guard let context, let controller = context.controller else { return }
|
|
context.showLoading()
|
|
let loadToken = UUID()
|
|
context.paginationToken = loadToken
|
|
|
|
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)
|
|
let publication = parser.makePublication()
|
|
let bookIdentifier = parser.metadata.identifier ?? controller.epubURL.lastPathComponent
|
|
let restoreLocation = controller.persistence?.loadLocation(for: bookIdentifier)
|
|
let bookmarks = controller.persistence?.loadBookmarks(for: bookIdentifier) ?? []
|
|
let highlights = controller.persistence?.loadHighlights(for: bookIdentifier) ?? []
|
|
|
|
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,
|
|
restoreLocation: restoreLocation,
|
|
bookmarks: bookmarks,
|
|
highlights: highlights
|
|
)
|
|
}
|
|
} catch {
|
|
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)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func applyParsedPublication(
|
|
parser: RDEPUBParser,
|
|
publication: RDEPUBPublication,
|
|
bookIdentifier: String,
|
|
restoreLocation: RDEPUBLocation?,
|
|
bookmarks: [RDEPUBBookmark],
|
|
highlights: [RDEPUBHighlight]
|
|
) {
|
|
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)
|
|
controller.title = parser.metadata.title.isEmpty
|
|
? controller.epubURL.deletingPathExtension().lastPathComponent
|
|
: parser.metadata.title
|
|
controller.applyReaderViewConfiguration()
|
|
context.updateReaderChrome()
|
|
controller.delegate?.epubReader(controller, didOpen: publication)
|
|
controller.applyOrientationLockIfNeeded()
|
|
context.runtime?.paginatePublication(restoreLocation: restoreLocation)
|
|
}
|
|
}
|