import Foundation /// EPUB 阅读器位置协调器:负责阅读位置的恢复、查询和持久化。 /// /// 职责: /// - 根据保存的位置恢复阅读进度 /// - 获取当前可见页面的阅读位置 /// - 从持久化存储加载已保存位置 /// - 持久化当前位置并通知委托 final class RDEPUBReaderLocationCoordinator { private unowned let context: RDEPUBReaderContext init(context: RDEPUBReaderContext) { self.context = context } /// 恢复到指定阅读位置,返回是否成功跳转。 @discardableResult func restoreReadingLocation(_ location: RDEPUBLocation, animated: Bool = false) -> Bool { guard let controller = context.controller, let readerView = context.readerView else { return false } guard let targetPageNumber = controller.pageNumber(for: location) else { readerView.transitionToPage(pageNum: 0) context.readingSession?.transition(to: .idle) return false } if context.bookPageMap != nil { guard context.runtime?.prepareOnDemandChapter(forAbsolutePageNumber: targetPageNumber) == true else { return false } _ = context.readingSession?.queueNavigation( to: location, relativeToSpineIndex: nil, bookIdentifier: context.currentBookIdentifier ) } else if context.textBook == nil { _ = context.readingSession?.queueNavigation( to: location, relativeToSpineIndex: nil, bookIdentifier: context.currentBookIdentifier ) } else { context.readingSession?.transition(to: .jumping) } readerView.transitionToPage(pageNum: max(targetPageNumber - 1, 0), animated: animated) return true } /// 获取当前可见页面对应的阅读位置。 func currentVisibleLocation() -> RDEPUBLocation? { guard let controller = context.controller, let readerView = context.readerView else { return nil } let pageNumber = readerView.currentPage + 1 if (context.textBook != nil || context.bookPageMap != nil), readerView.currentPage >= 0 { if let location = controller.resolvedTextLocation(forPageNumber: pageNumber) { return location } // resolvedTextLocation 可能因章节数据未加载而返回 nil, // 通过 readingSession 的 activePages 构建回退位置 if let readingSession = context.readingSession, readingSession.activePages.indices.contains(readerView.currentPage) { return readingSession.fallbackLocation( for: readingSession.activePages[readerView.currentPage], bookIdentifier: context.currentBookIdentifier ) } } return context.readingSession?.currentReadingLocation(bookIdentifier: context.currentBookIdentifier) } /// 从持久化存储加载上次保存的阅读位置。 func persistenceLocation() -> RDEPUBLocation? { guard let controller = context.controller, let currentBookIdentifier = context.currentBookIdentifier else { return nil } return controller.persistence?.loadLocation(for: currentBookIdentifier) } /// 持久化阅读位置,并通知委托更新目录项和书签状态。 func persist(location: RDEPUBLocation) { guard let controller = context.controller, let currentBookIdentifier = context.currentBookIdentifier else { return } controller.persistence?.saveLocation(location, for: currentBookIdentifier) controller.delegate?.epubReader(controller, didUpdateLocation: location) controller.delegate?.epubReader(controller, didUpdateCurrentTableOfContentsItem: controller.currentTableOfContentsItem) controller.updateBookmarkChrome() } }