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
@@ -96,7 +96,28 @@ extension RDEpubReaderView: UIPageViewControllerDataSource, UIPageViewController
}
public func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
let resolvedPage = (pageViewController.viewControllers?.first as? RDEpubReaderPageChildViewController)?.pageNum ?? -1
let visibleControllers = pageViewController.viewControllers ?? []
let visibleControllerIdentifiers = Set(visibleControllers.map(ObjectIdentifier.init))
let transitionControllers = previousViewControllers + [
willPreviousTransitionToViewController,
willNextTransitionToViewController,
willTransitionToViewController
].compactMap { $0 }
var hiddenContentViews = Set<ObjectIdentifier>()
// UIPageViewController can ask its data source for a second instance of
// the same page and leave the first one outside our cache dictionaries.
// Explicitly stop every controller that did not win the transition so
// an orphaned Hype WebView cannot keep narrating in the background.
for controller in transitionControllers where !visibleControllerIdentifiers.contains(ObjectIdentifier(controller)) {
guard let childController = controller as? RDEpubReaderPageChildViewController,
let contentView = childController.contentView else { continue }
let identifier = ObjectIdentifier(contentView)
guard hiddenContentViews.insert(identifier).inserted else { continue }
(contentView as? RDEpubReaderPageVisibilityHandling)?
.readerPageVisibilityDidChange(isVisible: false)
}
if completed, let firstVC = pageViewController.viewControllers?.first as? RDEpubReaderPageChildViewController {
let pn = firstVC.pageNum
if pn != RDEpubReaderView.blankPageNum && pn != RDEpubReaderView.blankEndPageNum {
@@ -105,6 +126,14 @@ extension RDEpubReaderView: UIPageViewControllerDataSource, UIPageViewController
}
}
// On cancellation currentPage does not change, so its didSet cannot
// restore visibility. Reassert the actual controllers in both paths.
for case let childController as RDEpubReaderPageChildViewController in visibleControllers {
guard let contentView = childController.contentView else { continue }
(contentView as? RDEpubReaderPageVisibilityHandling)?
.readerPageVisibilityDidChange(isVisible: isReaderPageVisible(childController.pageNum))
}
predictedPageDirection = nil
finishPageCurlTransition()
}