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
@@ -4,6 +4,8 @@ final class RDEPUBReaderChromeCoordinator: NSObject, UIAdaptivePresentationContr
private unowned let context: RDEPUBReaderContext
private var settingsTransitionDelegate: RDEPUBReaderSettingsTransitionDelegate?
init(context: RDEPUBReaderContext) {
self.context = context
}
@@ -122,9 +124,6 @@ final class RDEPUBReaderChromeCoordinator: NSObject, UIAdaptivePresentationContr
settingsController.onLineHeightChange = { [weak controller] lineHeightMultiple in
controller?.updateConfiguration { $0.lineHeightMultiple = lineHeightMultiple }
}
settingsController.onColumnCountChange = { [weak controller] numberOfColumns in
controller?.updateConfiguration { $0.numberOfColumns = numberOfColumns }
}
settingsController.onDisplayTypeChange = { [weak controller] displayType in
controller?.updateConfiguration { $0.displayType = displayType }
}
@@ -137,8 +136,13 @@ final class RDEPUBReaderChromeCoordinator: NSObject, UIAdaptivePresentationContr
}
let navigationController = UINavigationController(rootViewController: settingsController)
navigationController.modalPresentationStyle = .pageSheet
navigationController.presentationController?.delegate = self
let transitionDelegate = RDEPUBReaderSettingsTransitionDelegate()
settingsTransitionDelegate = transitionDelegate
navigationController.setNavigationBarHidden(true, animated: false)
navigationController.view.backgroundColor = .clear
navigationController.view.isOpaque = false
navigationController.modalPresentationStyle = .custom
navigationController.transitioningDelegate = transitionDelegate
controller.present(navigationController, animated: true)
}
@@ -233,3 +237,77 @@ final class RDEPUBReaderChromeCoordinator: NSObject, UIAdaptivePresentationContr
return candidate
}
}
private final class RDEPUBReaderSettingsTransitionDelegate: NSObject, UIViewControllerTransitioningDelegate {
func presentationController(
forPresented presented: UIViewController,
presenting: UIViewController?,
source: UIViewController
) -> UIPresentationController? {
RDEPUBReaderSettingsPresentationController(
presentedViewController: presented,
presenting: presenting ?? source
)
}
}
private final class RDEPUBReaderSettingsPresentationController: UIPresentationController {
private let dimmingView = UIControl()
override var frameOfPresentedViewInContainerView: CGRect {
guard let containerView else { return .zero }
let bounds = containerView.bounds
let isLandscape = bounds.width > bounds.height
if isLandscape {
let width = min(390, max(300, bounds.width * 0.32))
let height = min(340, bounds.height - 32)
return CGRect(
x: bounds.maxX - width - 16,
y: bounds.midY - height / 2,
width: width,
height: height
)
}
let height = min(350, max(280, bounds.height * 0.40))
return CGRect(x: 0, y: bounds.maxY - height, width: bounds.width, height: height)
}
override func presentationTransitionWillBegin() {
guard let containerView else { return }
dimmingView.backgroundColor = UIColor.black.withAlphaComponent(0.18)
dimmingView.alpha = 0
dimmingView.addTarget(self, action: #selector(dismissPresentedController), for: .touchUpInside)
dimmingView.frame = containerView.bounds
containerView.insertSubview(dimmingView, at: 0)
presentedViewController.transitionCoordinator?.animate(alongsideTransition: { _ in
self.dimmingView.alpha = 1
})
}
override func dismissalTransitionWillBegin() {
presentedViewController.transitionCoordinator?.animate(alongsideTransition: { _ in
self.dimmingView.alpha = 0
})
}
override func containerViewWillLayoutSubviews() {
super.containerViewWillLayoutSubviews()
dimmingView.frame = containerView?.bounds ?? .zero
presentedView?.frame = frameOfPresentedViewInContainerView
}
override func dismissalTransitionDidEnd(_ completed: Bool) {
super.dismissalTransitionDidEnd(completed)
if completed { dimmingView.removeFromSuperview() }
}
@objc private func dismissPresentedController() {
if let navigationController = presentedViewController as? UINavigationController,
let settingsController = navigationController.topViewController as? RDEPUBReaderSettingsViewController {
settingsController.notifyDismissalIfNeeded()
}
presentedViewController.dismiss(animated: true)
}
}