fix epub reader playback and trial navigation

This commit is contained in:
shen
2026-07-11 08:16:56 +08:00
parent d7fcda345d
commit 063a493b18
231 changed files with 435 additions and 36060 deletions
@@ -50,6 +50,10 @@ enum RDEpubReaderTapDebug {
public class RDEpubReaderView: UIView {
/// The readable-content gutter between two landscape pages. Each page
/// contributes half of this value from its inner content inset.
public static let landscapeDualPageGap: CGFloat = 10
enum TapEvent {
case none
@@ -93,6 +97,9 @@ public class RDEpubReaderView: UIView {
public var currentPage: Int = -1 {
didSet {
if currentPage != oldValue {
updatePageContentVisibility()
}
if let delegate = delegate, currentPage != oldValue, delegate.responds(to: #selector(RDEpubReaderDelegate.pageNum(readerView:pageNum:))) {
delegate.pageNum(readerView: self, pageNum: currentPage)
}
@@ -233,6 +240,13 @@ public class RDEpubReaderView: UIView {
)
}
/// Whether a page occupies the leading (left in LTR) side of a landscape
/// spread. Cover pages remain full-screen and are treated as leading.
public func isLeadingPage(_ pageNum: Int) -> Bool {
guard pagesPerScreen > 1, !isFullScreenPage(pageNum) else { return true }
return dualPagePair(for: pageNum).left == pageNum
}
private func dualPagePair(for pageNum: Int) -> (left: Int, right: Int?) {
let totalPages = numberOfPages()
return spreadResolver.dualPagePair(
@@ -380,6 +394,13 @@ public class RDEpubReaderView: UIView {
layout.isLandscapeDualPage = landscapeDualPageEnabled && isNowLandscape
layout.coverPageIndex = coverPageIndex
// Cached page views are configured with orientation-dependent content
// insets and Web render requests. Reusing a portrait-preloaded page in
// the rebuilt landscape page controller leaves the portrait safe-area
// inset on all four edges (and keeps fixed-layout Web content under the
// landscape sensor area). Drop them before requesting the new spread.
invalidatePageCaches()
switch currentDisplayType {
case .pageCurl:
@@ -503,11 +524,14 @@ public class RDEpubReaderView: UIView {
}
func pageViewForDisplay(pageNum: Int) -> UIView {
preloadController.pageViewForDisplay(
let pageView = preloadController.pageViewForDisplay(
pageNum: pageNum,
environment: preloadEnvironment,
contentViewProvider: pageContentViewForPreload(pageNum:reusableView:)
contentViewProvider: pageContentViewForDisplay(pageNum:reusableView:)
)
(pageView as? RDEpubReaderPageVisibilityHandling)?
.readerPageVisibilityDidChange(isVisible: isReaderPageVisible(pageNum))
return pageView
}
func primePageCache(around pageNum: Int, preferredForward: Bool? = nil) {
@@ -521,7 +545,50 @@ public class RDEpubReaderView: UIView {
}
private func pageContentViewForPreload(pageNum: Int, reusableView: UIView?) -> UIView? {
contentViewForPage(pageNum, reusableView: reusableView)
let allowsPreloading = resolvedPageProvider?
.readerView?(self, shouldPreloadPageAt: pageNum) ?? true
guard allowsPreloading else { return nil }
return contentViewForPage(pageNum, reusableView: reusableView)
}
private func pageContentViewForDisplay(pageNum: Int, reusableView: UIView?) -> UIView? {
return contentViewForPage(pageNum, reusableView: reusableView)
}
func isReaderPageVisible(_ pageNum: Int) -> Bool {
guard currentPage >= 0 else { return pageNum == 0 }
if landscapeDualPageEnabled && isLandscape {
let pair = dualPagePair(for: currentPage)
return pageNum == pair.left || pageNum == pair.right
}
return pageNum == currentPage
}
private func updatePageContentVisibility() {
var visiblePageNumbers = Set<Int>()
if currentPage >= 0 {
visiblePageNumbers.insert(currentPage)
if landscapeDualPageEnabled && isLandscape,
let rightPage = dualPagePair(for: currentPage).right {
visiblePageNumbers.insert(rightPage)
}
}
preloadController.updatePageVisibility(visiblePageNumbers: visiblePageNumbers)
for viewController in pageViewController.viewControllers ?? [] {
guard let pageController = viewController as? RDEpubReaderPageChildViewController,
let contentView = pageController.contentView else { continue }
(contentView as? RDEpubReaderPageVisibilityHandling)?
.readerPageVisibilityDidChange(isVisible: visiblePageNumbers.contains(pageController.pageNum))
}
for indexPath in collectionView.indexPathsForVisibleItems {
guard let cell = collectionView.cellForItem(at: indexPath) as? RDEpubReaderContentCell,
let contentView = cell.containerView else { continue }
(contentView as? RDEpubReaderPageVisibilityHandling)?
.readerPageVisibilityDidChange(isVisible: visiblePageNumbers.contains(indexPath.item))
}
}
public override func didMoveToSuperview() {