右对齐文本显示修复(如"巫鸿"只显示"鸿"的问题): - RDEPUBChapterTailNormalizer: 短尾页合并时检查 avoidPageBreakInside 语义, 避免将带有此标记的短文本(如 right-info 署名)错误合并回上一页 - RDEPUBTextContentView: 续段归一化时跳过右对齐/居中对齐的段落, 防止错误修改 firstLineHeadIndent 导致首字不可见 - RDEPUBCSSCompatibilityLayer: 为含 text-align:right/center 的 CSS 块 自动注入 text-indent:0 !important,确保右对齐/居中文本无首行缩进 - RDEPUBTextRendererSupport: 排版属性归一化时将右对齐/居中段落的 firstLineHeadIndent 重置为 0 图片查看器及脚注点击功能: - 新增 RDEPUBImageViewController 和 RDEPUBImageViewerCoordinator, 支持从 WebView 和 TextPage 两种模式查看图片 - epub-bridge.js: 检测图片和脚注图片的点击事件,脚注图片显示弹窗 - RDEPUBJavaScriptBridge: 新增 imageDidTap/footnoteDidTap 桥接消息 - RDEPUBWebView: 新增图片和脚注点击的 delegate 方法 - RDEPUBAttachmentNormalizer: 改进脚注检测,优先使用 alt 文本判断 - RDEPUBPaginationModels: 新增 .footnote 附件类型 - RDEPUBPageLayoutSnapshot: 运行时动态解析附件类型,脚注优先级高于图片 位置解析改进: - RDEPUBReaderController+LocationResolution: 利用 rangeInfo 提升页码定位精度 其他: - RDEPUBTextBookCache: schema 版本升级至 13 - RDEPUBReaderTheme: 主题更新 - Pod 项目文件更新 Co-Authored-By: Claude <noreply@anthropic.com>
60 lines
1.9 KiB
Swift
60 lines
1.9 KiB
Swift
import UIKit
|
|
|
|
final class RDEPUBImageViewerCoordinator {
|
|
|
|
private weak var presentingController: UIViewController?
|
|
private let theme: RDEPUBReaderTheme
|
|
|
|
init(presentingController: UIViewController, theme: RDEPUBReaderTheme) {
|
|
self.presentingController = presentingController
|
|
self.theme = theme
|
|
}
|
|
|
|
// MARK: - From Native Text Path (UIImage already resolved)
|
|
|
|
func presentImage(_ image: UIImage, sourceRect: CGRect? = nil, altText: String? = nil) {
|
|
let config = RDEPUBImageViewController.Configuration(
|
|
image: image,
|
|
sourceRect: sourceRect,
|
|
altText: altText,
|
|
theme: theme
|
|
)
|
|
let viewerVC = RDEPUBImageViewController(configuration: config)
|
|
presentingController?.present(viewerVC, animated: true)
|
|
}
|
|
|
|
// MARK: - From WebView Path (need to resolve from src URL)
|
|
|
|
func presentImageFromWebView(
|
|
src: String,
|
|
baseHref: String?,
|
|
resourceResolver: RDEPUBResourceResolver
|
|
) {
|
|
guard let image = loadImage(src: src, baseHref: baseHref, resourceResolver: resourceResolver) else {
|
|
return
|
|
}
|
|
presentImage(image)
|
|
}
|
|
|
|
// MARK: - Private
|
|
|
|
private func loadImage(
|
|
src: String,
|
|
baseHref: String?,
|
|
resourceResolver: RDEPUBResourceResolver
|
|
) -> UIImage? {
|
|
let pathPart = src.components(separatedBy: "#").first ?? src
|
|
guard !pathPart.isEmpty else { return nil }
|
|
|
|
let fileURL: URL?
|
|
if let baseHref {
|
|
fileURL = resourceResolver.fileURL(forReference: pathPart, relativeToHref: baseHref)
|
|
} else {
|
|
let normalized = resourceResolver.normalizedHref(pathPart)
|
|
fileURL = normalized.flatMap { resourceResolver.fileURL(forRelativePath: $0) }
|
|
}
|
|
|
|
guard let fileURL, let data = try? Data(contentsOf: fileURL) else { return nil }
|
|
return UIImage(data: data)
|
|
}
|
|
} |