feat: improve epub reader controls and annotations

This commit is contained in:
shen
2026-07-12 12:23:10 +08:00
parent 063a493b18
commit 8ccb7157b2
36 changed files with 2959 additions and 2160 deletions
@@ -127,14 +127,19 @@ final class RDEpubReaderPreloadController {
return preloaded
}
func updatePageVisibility(visiblePageNumbers: Set<Int>) {
var notifiedViews = Set<ObjectIdentifier>()
func updatePageVisibility(visibleViewIdentifiers: Set<ObjectIdentifier>) {
let cachedViews = pageCurlCachedViews.merging(preloadedPageViews) { current, _ in current }
for (pageNumber, view) in cachedViews {
var notifiedViews = Set<ObjectIdentifier>()
// Cache entries are never the authority for activation: UIPageViewController
// can create two views for the same page number. Keep every non-winning
// instance suspended; the reader activates only its actually attached view.
for view in cachedViews.values {
let identifier = ObjectIdentifier(view)
guard notifiedViews.insert(identifier).inserted else { continue }
guard !visibleViewIdentifiers.contains(identifier),
notifiedViews.insert(identifier).inserted else { continue }
(view as? RDEpubReaderPageVisibilityHandling)?
.readerPageVisibilityDidChange(isVisible: visiblePageNumbers.contains(pageNumber))
.readerPageVisibilityDidChange(isVisible: false)
}
}
@@ -147,7 +152,7 @@ final class RDEpubReaderPreloadController {
) {
refreshCacheSignatureIfNeeded(environment)
let targets = forecastTargets(around: pageNum, preferredForward: preferredForward, environment: environment)
let keepSet = Set(targets).union(visiblePageNumbers(for: pageNum, environment: environment))
let keepSet = Set(targets).union(spreadPageNumbers(startingAt: pageNum, environment: environment))
trimCachedPageViews(keeping: keepSet)
guard !targets.isEmpty else { return }
@@ -194,6 +199,8 @@ final class RDEpubReaderPreloadController {
"cache MISS page=\(targetPage) created=\(RDEpubReaderTapDebug.describe(contentView))"
)
}
(contentView as? RDEpubReaderPageVisibilityHandling)?
.readerPageVisibilityDidChange(isVisible: false)
let shouldCacheContentView = shouldCache(view: contentView, for: targetPage, environment: environment)
if shouldCacheContentView {
preloadedPageViews[targetPage] = contentView
@@ -309,10 +316,6 @@ final class RDEpubReaderPreloadController {
).left
}
private func visiblePageNumbers(for anchorPage: Int, environment: Environment) -> Set<Int> {
spreadPageNumbers(startingAt: anchorPage, environment: environment)
}
private func detachedReusablePageView(for pageNum: Int) -> UIView? {
if let preloaded = preloadedPageViews.removeValue(forKey: pageNum) {
preloaded.removeFromSuperview()
@@ -351,6 +354,8 @@ final class RDEpubReaderPreloadController {
//
// deinit
let isHeldOutsidePreloadHost = view.superview != nil && view.superview !== preloadHostView
(view as? RDEpubReaderPageVisibilityHandling)?
.readerPageVisibilityDidChange(isVisible: false)
view.removeFromSuperview()
if !isHeldOutsidePreloadHost {
(view as? RDEpubReaderPageResourceReleasing)?.releaseResources()