refactor: rename RDReaderView -> RDEpubReaderView, update pod config and docs

- Rename source module from RDReaderView to RDEpubReaderView
- Move all source files from Sources/RDReaderView/ to Sources/RDEpubReaderView/
- Update podspec: RDReaderView.podspec -> RDEpubReaderView.podspec
- Update Podfile, demo project, and CocoaPods config for new pod name
- Delete old RDReaderView pod support files from ReadViewDemo/Pods
- Add new RDEpubReaderView pod support files
- Update documentation (API ref, architecture, UML, conventions, etc.)
- Add FixedLayoutRotationTests
- Update .gitignore: exclude .DS_Store, manual unpack backups, _ssoft-output
This commit is contained in:
shenlei
2026-07-10 19:44:53 +09:00
parent d5a7755702
commit d7fcda345d
460 changed files with 38358 additions and 2300 deletions
@@ -0,0 +1,132 @@
import UIKit
import WebKit
extension RDEPUBWebView {
func configureWebViewIfNeeded(publication: RDEPUBPublication) {
let parser = publication.parser
let publicationKey = parser.opfURL?.path ?? parser.extractionRootURL?.path ?? UUID().uuidString
if publicationKey == configuredPublicationKey, webView != nil {
return
}
teardownWebView()
let userContentController = WKUserContentController()
let messageHandlerProxy = RDEPUBWeakScriptMessageHandler(target: self)
RDEPUBJavaScriptBridge.messageNames.forEach {
userContentController.add(messageHandlerProxy, name: $0)
}
userContentController.addUserScript(
WKUserScript(
source: RDEPUBJavaScriptBridge.userScript,
injectionTime: .atDocumentEnd,
forMainFrameOnly: true
)
)
let configuration = WKWebViewConfiguration()
configuration.websiteDataStore = .nonPersistent()
configuration.userContentController = userContentController
let schemeHandler = RDEPUBResourceURLSchemeHandler(parser: parser)
configuration.setURLSchemeHandler(schemeHandler, forURLScheme: RDEPUBResourceURLSchemeHandler.scheme)
let webView = RDEPUBAnnotationWebView(frame: bounds, configuration: configuration)
webView.onSelectionAction = { [weak self] action in
guard let self else { return }
self.handleSelectionMenuAction(action)
}
// M-15: Use UIEditMenuInteraction on iOS 16+ to replace deprecated UIMenuController
if #available(iOS 16.0, *) {
let interaction = UIEditMenuInteraction(delegate: webView)
webView.addInteraction(interaction)
webView._editMenuInteraction = interaction
} else {
UIMenuController.shared.menuItems = [
UIMenuItem(title: "拷贝", action: #selector(RDEPUBAnnotationWebView.rd_copy(_:))),
UIMenuItem(title: "高亮", action: #selector(RDEPUBAnnotationWebView.rd_highlight(_:))),
UIMenuItem(title: "批注", action: #selector(RDEPUBAnnotationWebView.rd_annotate(_:)))
]
}
webView.navigationDelegate = self
// Web 59pt 21pt
// /
// fixedContentInset / CSS
webView.scrollView.contentInsetAdjustmentBehavior = .never
webView.scrollView.isScrollEnabled = false
webView.scrollView.showsHorizontalScrollIndicator = false
webView.scrollView.showsVerticalScrollIndicator = false
webView.scrollView.bounces = false
webView.scrollView.alwaysBounceHorizontal = false
webView.scrollView.alwaysBounceVertical = false
webView.scrollView.clipsToBounds = true
webView.scrollView.panGestureRecognizer.isEnabled = false
webView.scrollView.pinchGestureRecognizer?.isEnabled = false
webView.isOpaque = false
webView.backgroundColor = .clear
webView.clipsToBounds = true
if #available(iOS 16.4, *) {
webView.isInspectable = RDEPUBWebViewDebug.isInspectableEnabled
}
addSubview(webView)
webView.frame = bounds
webView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
self.schemeHandler = schemeHandler
self.webView = webView
self.configuredPublicationKey = publicationKey
RDEPUBWebViewDebug.log(debugScope, message: "configured webView=\(RDEPUBWebViewDebug.webViewID(webView)) publicationKey=\(publicationKey)")
}
func handleSelectionMenuAction(_ action: RDEPUBAnnotationMenuAction) {
delegate?.epubWebView(self, didRequestSelectionAction: action)
clearWebSelection()
}
func clearWebSelection() {
webView?.evaluateJavaScript("window.getSelection && window.getSelection().removeAllRanges();")
}
func teardownWebView() {
cancelFixedLayoutReadyFallback()
if let webView {
RDEPUBWebViewDebug.log(debugScope, message: "teardown webView=\(RDEPUBWebViewDebug.webViewID(webView))")
}
// M-15: Clean up UIEditMenuInteraction on iOS 16+
if #available(iOS 16.0, *), let interaction = (webView as? RDEPUBAnnotationWebView)?._editMenuInteraction as? UIEditMenuInteraction {
webView?.removeInteraction(interaction)
}
webView?.navigationDelegate = nil
if let userContentController = webView?.configuration.userContentController {
RDEPUBJavaScriptBridge.messageNames.forEach {
userContentController.removeScriptMessageHandler(forName: $0)
}
}
(webView as? RDEPUBAnnotationWebView)?.onSelectionAction = nil
webView?.removeFromSuperview()
webView = nil
schemeHandler = nil
configuredPublicationKey = nil
currentLoadSignature = nil
}
}
/// M-08: WKUserContentController script message handler
/// RDEPUBWebView
/// webView userContentController RDEPUBWebView webView
/// WebView handler
/// RDEPUBWebView deinit
private final class RDEPUBWeakScriptMessageHandler: NSObject, WKScriptMessageHandler {
private weak var target: WKScriptMessageHandler?
init(target: WKScriptMessageHandler) {
self.target = target
}
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
target?.userContentController(userContentController, didReceive: message)
}
}