ReadViewSDK/Sources/RDEpubReaderView/EPUBUI/RDEPUBWebContentView.swift

140 lines
5.7 KiB
Swift

import UIKit
protocol RDEPUBWebContentViewDelegate: AnyObject {
func epubWebContentView(_ contentView: RDEPUBWebContentView, didUpdateLocation location: RDEPUBLocation, spineIndex: Int)
func epubWebContentView(_ contentView: RDEPUBWebContentView, didChangeSelection selection: RDEPUBSelection?, spineIndex: Int)
func epubWebContentView(_ contentView: RDEPUBWebContentView, didRequestSelectionAction action: RDEPUBAnnotationMenuAction)
func epubWebContentView(_ contentView: RDEPUBWebContentView, didActivateInternalLink location: RDEPUBLocation, fromSpineIndex: Int)
func epubWebContentView(_ contentView: RDEPUBWebContentView, didActivateExternalLink url: URL)
func epubWebContentView(_ contentView: RDEPUBWebContentView, didLogJavaScriptError message: String)
func epubWebContentView(_ contentView: RDEPUBWebContentView, didTapImageWithSource src: String, sourceRect: CGRect?)
func epubWebContentView(_ contentView: RDEPUBWebContentView, didTapFootnoteWithAltText altText: String, sourceRect: CGRect?)
}
final class RDEPUBWebContentView: UIView, RDEpubReaderPageResourceReleasing, RDEpubReaderPageVisibilityHandling {
weak var delegate: RDEPUBWebContentViewDelegate?
/// The current href of the loaded chapter (exposed for image resolution).
var currentHref: String {
epubWebView.currentHref
}
private let epubWebView = RDEPUBWebView()
private let decorationOverlayView = RDEPUBWebDecorationOverlayView()
private let pageNumberLabel: UILabel = {
let label = UILabel()
label.font = UIFont.systemFont(ofSize: 13)
return label
}()
override init(frame: CGRect) {
super.init(frame: frame)
clipsToBounds = true
layer.masksToBounds = true
addSubview(epubWebView)
addSubview(decorationOverlayView)
addSubview(pageNumberLabel)
epubWebView.delegate = self
epubWebView.onDecorationsResolved = { [weak self] decorations in
self?.decorationOverlayView.applyDecorations(decorations)
}
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layoutSubviews() {
super.layoutSubviews()
epubWebView.frame = bounds
decorationOverlayView.frame = bounds
let labelSize = pageNumberLabel.sizeThatFits(CGSize(width: bounds.width, height: 20))
pageNumberLabel.frame = CGRect(
x: bounds.width - labelSize.width - 24,
y: bounds.height - labelSize.height - 20,
width: labelSize.width,
height: labelSize.height
)
}
func configure(
publication: RDEPUBPublication,
request: RDEPUBRenderRequest,
pageNumber: Int,
totalPages: Int,
theme: RDEPUBReaderTheme
) {
backgroundColor = theme.contentBackgroundColor
pageNumberLabel.textColor = theme.contentTextColor
pageNumberLabel.text = "\(pageNumber) / \(totalPages)"
decorationOverlayView.applyDecorations([])
epubWebView.load(publication: publication, request: request)
setNeedsLayout()
}
func releaseResources() {
decorationOverlayView.applyDecorations([])
epubWebView.reset()
epubWebView.delegate = self
epubWebView.onDecorationsResolved = { [weak self] decorations in
self?.decorationOverlayView.applyDecorations(decorations)
}
}
func readerPageVisibilityDidChange(isVisible: Bool) {
epubWebView.setReaderPageVisible(isVisible)
}
}
extension RDEPUBWebContentView: RDEPUBWebViewDelegate {
func epubWebView(_ webView: RDEPUBWebView, didUpdateLocation location: RDEPUBLocation, spineIndex: Int) {
delegate?.epubWebContentView(self, didUpdateLocation: location, spineIndex: spineIndex)
}
func epubWebView(_ webView: RDEPUBWebView, didChangeSelection selection: RDEPUBSelection?, spineIndex: Int) {
delegate?.epubWebContentView(self, didChangeSelection: selection, spineIndex: spineIndex)
}
func epubWebView(_ webView: RDEPUBWebView, didRequestSelectionAction action: RDEPUBAnnotationMenuAction) {
delegate?.epubWebContentView(self, didRequestSelectionAction: action)
}
func epubWebView(_ webView: RDEPUBWebView, didActivateInternalLink location: RDEPUBLocation, fromSpineIndex: Int) {
delegate?.epubWebContentView(self, didActivateInternalLink: location, fromSpineIndex: fromSpineIndex)
}
func epubWebView(_ webView: RDEPUBWebView, didActivateExternalLink url: URL) {
delegate?.epubWebContentView(self, didActivateExternalLink: url)
}
func epubWebView(_ webView: RDEPUBWebView, didLogJavaScriptError message: String) {
delegate?.epubWebContentView(self, didLogJavaScriptError: message)
}
func epubWebViewDidFinishRendering(_ webView: RDEPUBWebView) {}
func epubWebView(_ webView: RDEPUBWebView, didTapImageWithSource src: String, sourceRect: CGRect?) {
delegate?.epubWebContentView(self, didTapImageWithSource: src, sourceRect: sourceRect)
}
func epubWebView(_ webView: RDEPUBWebView, didTapFootnoteWithAltText altText: String, sourceRect: CGRect?) {
delegate?.epubWebContentView(self, didTapFootnoteWithAltText: altText, sourceRect: sourceRect)
}
}
extension RDEPUBWebContentViewDelegate {
func epubWebContentView(_ contentView: RDEPUBWebContentView, didTapImageWithSource src: String, sourceRect: CGRect?) {
// Default: no-op. Implementors can present an image viewer.
}
func epubWebContentView(_ contentView: RDEPUBWebContentView, didTapFootnoteWithAltText altText: String, sourceRect: CGRect?) {
// Default: no-op. Implementors can present a footnote tooltip.
}
}