feat(reader): 增强阅读器功能与 UI 测试支持
- 新增字体选择(系统/宋体/圆体/等宽)与暗色图片柔化配置 - 文本选择改为自定义手势+操作栏(拷贝/高亮/批注) - 添加 accessibilityIdentifier 支持自动化 UI 测试 - 新增 UITests 覆盖阅读器打开/关闭、工具栏、设置面板、批注等 - 添加 Demo 测试用 EPUB 书源(宝山辽墓材料与释读) - 新增文档:UI 自动化测试、功能开发计划、阅读器规划
This commit is contained in:
@@ -31,6 +31,16 @@ public final class RDURLReaderController: UIViewController {
|
||||
private let epubConfiguration: RDEPUBReaderConfiguration
|
||||
/// 内嵌的阅读器控制器
|
||||
private var embeddedController: UIViewController?
|
||||
private let demoStateLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.accessibilityIdentifier = "demo.reader.state"
|
||||
label.font = .systemFont(ofSize: 1)
|
||||
label.textColor = .clear
|
||||
label.alpha = 0.01
|
||||
label.isAccessibilityElement = true
|
||||
label.text = "reader=opening"
|
||||
return label
|
||||
}()
|
||||
|
||||
/// 初始化方法
|
||||
/// - Parameters:
|
||||
@@ -56,13 +66,19 @@ public final class RDURLReaderController: UIViewController {
|
||||
view.backgroundColor = .systemBackground
|
||||
title = bookURL.deletingPathExtension().lastPathComponent
|
||||
embedReaderController()
|
||||
installDemoStateLabel()
|
||||
}
|
||||
|
||||
public override func viewDidAppear(_ animated: Bool) {
|
||||
super.viewDidAppear(animated)
|
||||
emitDemoState()
|
||||
}
|
||||
|
||||
/// 切换阅读器的翻页模式(Demo 用)
|
||||
/// - Parameter displayType: 目标翻页模式
|
||||
public func applyDemoDisplayType(_ displayType: RDReaderView.DisplayType) {
|
||||
readerController?.configuration.displayType = displayType
|
||||
logDemoState(prefix: "display=\(displayType.demoArgumentValue)")
|
||||
emitDemoState(prefix: "display=\(displayType.demoArgumentValue)")
|
||||
}
|
||||
|
||||
/// 跳转到指定页码(Demo 用)
|
||||
@@ -74,7 +90,7 @@ public final class RDURLReaderController: UIViewController {
|
||||
public func goToDemoPage(_ pageNumber: Int, animated: Bool = false) -> Bool {
|
||||
let moved = readerController?.go(toPageNumber: pageNumber, animated: animated) ?? false
|
||||
if moved {
|
||||
logDemoState(prefix: "page=\(pageNumber)")
|
||||
emitDemoState(prefix: "page=\(pageNumber)")
|
||||
}
|
||||
return moved
|
||||
}
|
||||
@@ -162,6 +178,8 @@ public final class RDURLReaderController: UIViewController {
|
||||
controller.view.bottomAnchor.constraint(equalTo: view.bottomAnchor),
|
||||
])
|
||||
controller.didMove(toParent: self)
|
||||
readerController?.delegate = self
|
||||
emitDemoState()
|
||||
}
|
||||
|
||||
/// 获取内嵌的 EPUB 阅读器控制器(如果存在)
|
||||
@@ -179,6 +197,32 @@ public final class RDURLReaderController: UIViewController {
|
||||
print("[ReadViewDemo] automation \(prefix) -> page \(page) href \(href) progression \(progression)")
|
||||
}
|
||||
|
||||
private func installDemoStateLabel() {
|
||||
view.addSubview(demoStateLabel)
|
||||
demoStateLabel.translatesAutoresizingMaskIntoConstraints = false
|
||||
NSLayoutConstraint.activate([
|
||||
demoStateLabel.leadingAnchor.constraint(equalTo: view.leadingAnchor),
|
||||
demoStateLabel.topAnchor.constraint(equalTo: view.topAnchor),
|
||||
demoStateLabel.widthAnchor.constraint(equalToConstant: 1),
|
||||
demoStateLabel.heightAnchor.constraint(equalToConstant: 1)
|
||||
])
|
||||
}
|
||||
|
||||
private func emitDemoState(prefix: String? = nil) {
|
||||
let page = readerController?.currentPageNumber.map(String.init) ?? "nil"
|
||||
let display = readerController?.configuration.displayType.demoArgumentValue ?? epubConfiguration.displayType.demoArgumentValue
|
||||
let toolbar = readerController?.readerView.isShowToolView == true ? "visible" : "hidden"
|
||||
let highlights = readerController?.highlights.count ?? 0
|
||||
let selection = readerController?.currentSelection == nil ? 0 : 1
|
||||
let state = "reader=opened page=\(page) display=\(display) toolbar=\(toolbar) highlights=\(highlights) selection=\(selection)"
|
||||
demoStateLabel.text = state
|
||||
if let prefix {
|
||||
logDemoState(prefix: prefix)
|
||||
} else {
|
||||
print("[ReadViewDemo] automation \(state)")
|
||||
}
|
||||
}
|
||||
|
||||
/// 计算文本分页的页面尺寸。
|
||||
/// 分页器使用完整 viewport,真实可绘制区域由 layoutConfig.edgeInsets 控制,
|
||||
/// 以保持与页面展示时的内容几何一致。
|
||||
@@ -188,7 +232,7 @@ public final class RDURLReaderController: UIViewController {
|
||||
|
||||
/// 根据当前配置生成文本渲染样式
|
||||
private func currentTextRenderStyle() -> RDEPUBTextRenderStyle {
|
||||
let font = UIFont.systemFont(ofSize: epubConfiguration.fontSize)
|
||||
let font = epubConfiguration.fontChoice.font(ofSize: epubConfiguration.fontSize)
|
||||
let lineSpacing = max(font.lineHeight * (epubConfiguration.lineHeightMultiple - 1), 4)
|
||||
return RDEPUBTextRenderStyle(
|
||||
font: font,
|
||||
@@ -214,6 +258,20 @@ public final class RDURLReaderController: UIViewController {
|
||||
}
|
||||
}
|
||||
|
||||
extension RDURLReaderController: RDEPUBReaderDelegate {
|
||||
public func epubReader(_ reader: UIViewController, didUpdateLocation location: RDEPUBLocation) {
|
||||
emitDemoState()
|
||||
}
|
||||
|
||||
public func epubReader(_ reader: UIViewController, didChangeSelection selection: RDEPUBSelection?) {
|
||||
emitDemoState(prefix: "selection=\(selection == nil ? 0 : 1)")
|
||||
}
|
||||
|
||||
public func epubReader(_ reader: UIViewController, didUpdateHighlights highlights: [RDEPUBHighlight]) {
|
||||
emitDemoState(prefix: "highlights=\(highlights.count)")
|
||||
}
|
||||
}
|
||||
|
||||
/// 翻页模式扩展:提供 Demo 命令行参数值
|
||||
private extension RDReaderView.DisplayType {
|
||||
/// 返回翻页模式对应的 Demo 命令行参数字符串
|
||||
|
||||
Reference in New Issue
Block a user