106 lines
4.1 KiB
Swift
106 lines
4.1 KiB
Swift
import UIKit
|
|
|
|
public final class RDURLReaderController: UIViewController {
|
|
private let bookURL: URL
|
|
private let epubConfiguration: RDEPUBReaderConfiguration
|
|
private var embeddedController: UIViewController?
|
|
|
|
public init(
|
|
bookURL: URL,
|
|
epubConfiguration: RDEPUBReaderConfiguration = RDEPUBReaderConfiguration()
|
|
) {
|
|
self.bookURL = bookURL
|
|
self.epubConfiguration = epubConfiguration
|
|
super.init(nibName: nil, bundle: nil)
|
|
}
|
|
|
|
@available(*, unavailable)
|
|
required init?(coder: NSCoder) {
|
|
fatalError("init(coder:) has not been implemented")
|
|
}
|
|
|
|
public override func viewDidLoad() {
|
|
super.viewDidLoad()
|
|
view.backgroundColor = .systemBackground
|
|
title = bookURL.deletingPathExtension().lastPathComponent
|
|
embedReaderController()
|
|
}
|
|
|
|
private func embedReaderController() {
|
|
let controller: UIViewController
|
|
if bookURL.pathExtension.lowercased() == "epub" {
|
|
controller = RDEPUBReaderController(
|
|
epubURL: bookURL,
|
|
configuration: epubConfiguration
|
|
)
|
|
} else {
|
|
let bookIdentifier = bookURL.lastPathComponent
|
|
let bookTitle = bookURL.deletingPathExtension().lastPathComponent
|
|
let pageSize = currentTextPageSize()
|
|
let renderStyle = currentTextRenderStyle()
|
|
let builder = RDPlainTextBookBuilder()
|
|
if let textBook = try? builder.build(textFileURL: bookURL, pageSize: pageSize, style: renderStyle) {
|
|
controller = RDEPUBReaderController(
|
|
textBook: textBook,
|
|
bookIdentifier: bookIdentifier,
|
|
title: bookTitle,
|
|
textFileURL: bookURL,
|
|
configuration: epubConfiguration
|
|
)
|
|
} else {
|
|
// 分页失败时回退到纯文本展示
|
|
let fallback = UIViewController()
|
|
let textView = UITextView()
|
|
textView.isEditable = false
|
|
textView.text = rd_decodeTextFile(url: bookURL)
|
|
fallback.view = textView
|
|
controller = fallback
|
|
}
|
|
}
|
|
embeddedController = controller
|
|
addChild(controller)
|
|
controller.view.translatesAutoresizingMaskIntoConstraints = false
|
|
view.addSubview(controller.view)
|
|
NSLayoutConstraint.activate([
|
|
controller.view.topAnchor.constraint(equalTo: view.topAnchor),
|
|
controller.view.leadingAnchor.constraint(equalTo: view.leadingAnchor),
|
|
controller.view.trailingAnchor.constraint(equalTo: view.trailingAnchor),
|
|
controller.view.bottomAnchor.constraint(equalTo: view.bottomAnchor),
|
|
])
|
|
controller.didMove(toParent: self)
|
|
}
|
|
|
|
private func currentTextPageSize() -> CGSize {
|
|
let viewportSize = UIScreen.main.bounds.size
|
|
let insets = epubConfiguration.reflowableContentInsets
|
|
return CGSize(
|
|
width: max(viewportSize.width - insets.left - insets.right, 1),
|
|
height: max(viewportSize.height - insets.top - insets.bottom, 1)
|
|
)
|
|
}
|
|
|
|
private func currentTextRenderStyle() -> RDEPUBTextRenderStyle {
|
|
let font = UIFont.systemFont(ofSize: epubConfiguration.fontSize)
|
|
let lineSpacing = max(font.lineHeight * (epubConfiguration.lineHeightMultiple - 1), 4)
|
|
return RDEPUBTextRenderStyle(
|
|
font: font,
|
|
lineSpacing: lineSpacing,
|
|
textColor: epubConfiguration.theme.contentTextColor,
|
|
backgroundColor: epubConfiguration.theme.contentBackgroundColor
|
|
)
|
|
}
|
|
|
|
private func rd_decodeTextFile(url: URL) -> String {
|
|
if let content = try? NSString(contentsOf: url, encoding: String.Encoding.utf8.rawValue) as String {
|
|
return content
|
|
}
|
|
if let content = try? NSString(contentsOf: url, encoding: 0x80000632) as String {
|
|
return content
|
|
}
|
|
if let content = try? NSString(contentsOf: url, encoding: 0x80000631) as String {
|
|
return content
|
|
}
|
|
return ""
|
|
}
|
|
}
|