目前阅读稳定版本,需要修改图片阅读方式

This commit is contained in:
shen
2026-05-23 15:50:53 +08:00
parent d7339aa255
commit 3e2669d8a8
7 changed files with 450 additions and 9 deletions
@@ -1,6 +1,10 @@
import UIKit
import Foundation
#if canImport(DTCoreText)
import DTCoreText
#endif
protocol RDEPUBTextContentViewDelegate: AnyObject {
func textContentView(_ contentView: RDEPUBTextContentView, didChangeSelection selection: RDEPUBSelection?)
func textContentView(_ contentView: RDEPUBTextContentView, didRequestSelectionAction action: RDEPUBAnnotationMenuAction)
@@ -50,6 +54,13 @@ final class RDEPUBTextContentView: UIView {
return view
}()
private let coverImageView: UIImageView = {
let view = UIImageView()
view.contentMode = .scaleAspectFit
view.isHidden = true
return view
}()
private let pageNumberLabel: UILabel = {
let label = UILabel()
label.font = UIFont.systemFont(ofSize: 13)
@@ -58,6 +69,7 @@ final class RDEPUBTextContentView: UIView {
override init(frame: CGRect) {
super.init(frame: frame)
addSubview(coverImageView)
addSubview(textView)
addSubview(pageNumberLabel)
textView.delegate = self
@@ -80,6 +92,7 @@ final class RDEPUBTextContentView: UIView {
super.layoutSubviews()
textView.frame = bounds.inset(by: contentInsets)
coverImageView.frame = bounds.inset(by: contentInsets)
let labelSize = pageNumberLabel.sizeThatFits(CGSize(width: bounds.width, height: 20))
pageNumberLabel.frame = CGRect(
@@ -105,6 +118,17 @@ final class RDEPUBTextContentView: UIView {
pageNumberLabel.textColor = configuration.theme.contentTextColor
pageNumberLabel.text = "\(pageNumber) / \(totalPages)"
if configureCoverIfNeeded(for: page) {
textView.attributedText = nil
textView.selectedRange = NSRange(location: 0, length: 0)
delegate?.textContentView(self, didChangeSelection: nil)
setNeedsLayout()
return
}
coverImageView.isHidden = true
coverImageView.image = nil
let displayContent = NSMutableAttributedString(attributedString: page.content)
let fullRange = NSRange(location: 0, length: displayContent.length)
displayContent.addAttribute(
@@ -112,6 +136,7 @@ final class RDEPUBTextContentView: UIView {
value: configuration.theme.contentTextColor,
range: fullRange
)
normalizeInlineAttachments(in: displayContent, basePointSize: configuration.fontSize)
applyHighlights(to: displayContent, page: page)
applySearchHighlights(to: displayContent, page: page, searchState: searchState)
textView.tintColor = configuration.theme.toolControlTextColor
@@ -189,6 +214,73 @@ final class RDEPUBTextContentView: UIView {
return lowerBound..<max(upperBound, lowerBound)
}
private func configureCoverIfNeeded(for page: RDEPUBTextPage) -> Bool {
guard page.pageIndexInChapter == 0,
page.href.lowercased().contains("cover"),
let image = coverImage(from: page.content) else {
return false
}
coverImageView.image = image
coverImageView.isHidden = false
textView.attributedText = nil
return true
}
private func coverImage(from content: NSAttributedString) -> UIImage? {
guard content.length > 0 else { return nil }
var resolvedImage: UIImage?
content.enumerateAttribute(.attachment, in: NSRange(location: 0, length: content.length)) { value, _, stop in
guard let image = image(from: value) else { return }
resolvedImage = image
stop.pointee = true
}
return resolvedImage
}
private func image(from attachmentValue: Any?) -> UIImage? {
#if canImport(DTCoreText)
if let attachment = attachmentValue as? DTTextAttachment,
let url = attachment.contentURL {
return UIImage(contentsOfFile: url.path)
}
#endif
if let attachment = attachmentValue as? NSTextAttachment {
if let image = attachment.image {
return image
}
if let data = attachment.contents {
return UIImage(data: data)
}
if let fileWrapper = attachment.fileWrapper,
let data = fileWrapper.regularFileContents {
return UIImage(data: data)
}
}
return nil
}
private func normalizeInlineAttachments(in content: NSMutableAttributedString, basePointSize: CGFloat) {
guard content.length > 0 else { return }
content.enumerateAttribute(.attachment, in: NSRange(location: 0, length: content.length)) { value, range, _ in
#if canImport(DTCoreText)
if let attachment = value as? DTTextAttachment {
let classes = ((attachment.attributes["class"] as? String) ?? "").lowercased()
let source = (attachment.contentURL?.lastPathComponent ?? (attachment.attributes["src"] as? String) ?? "").lowercased()
guard classes.contains("qqreader-footnote") || source.contains("note.png") else { return }
let pointSize = max(basePointSize, 1)
let targetHeight = max(round(pointSize * 0.14), 1)
let aspectRatio = attachment.originalSize.height > 0 ? attachment.originalSize.width / attachment.originalSize.height : 1
let targetWidth = max(round(targetHeight * max(aspectRatio, 0.1)), 1)
attachment.displaySize = CGSize(width: targetWidth, height: targetHeight)
attachment.verticalAlignment = .center
content.addAttribute(.attachment, value: attachment, range: range)
}
#endif
}
}
}
extension RDEPUBTextContentView: UITextViewDelegate {