feat(reader): 增强阅读器功能与 UI 测试支持

- 新增字体选择(系统/宋体/圆体/等宽)与暗色图片柔化配置
- 文本选择改为自定义手势+操作栏(拷贝/高亮/批注)
- 添加 accessibilityIdentifier 支持自动化 UI 测试
- 新增 UITests 覆盖阅读器打开/关闭、工具栏、设置面板、批注等
- 添加 Demo 测试用 EPUB 书源(宝山辽墓材料与释读)
- 新增文档:UI 自动化测试、功能开发计划、阅读器规划
This commit is contained in:
shen
2026-05-31 23:56:54 +08:00
parent 44202357c0
commit 1efb9d172f
268 changed files with 4991 additions and 44 deletions
@@ -9,6 +9,51 @@ public enum RDEPUBTextRenderingEngine: Equatable {
case dtCoreText
}
// MARK: -
///
/// 使 bundle
public enum RDEPUBReaderFontChoice: String, Codable, CaseIterable, Equatable {
/// 线
case system
/// 线
case serif
///
case rounded
///
case monospaced
public var displayName: String {
switch self {
case .system:
return "系统"
case .serif:
return "宋体"
case .rounded:
return "圆体"
case .monospaced:
return "等宽"
}
}
public func font(ofSize size: CGFloat) -> UIFont {
switch self {
case .system:
return UIFont.systemFont(ofSize: size)
case .serif:
let descriptor = UIFontDescriptor.preferredFontDescriptor(withTextStyle: .body)
.withDesign(.serif) ?? UIFontDescriptor.preferredFontDescriptor(withTextStyle: .body)
return UIFont(descriptor: descriptor, size: size)
case .rounded:
let descriptor = UIFontDescriptor.preferredFontDescriptor(withTextStyle: .body)
.withDesign(.rounded) ?? UIFontDescriptor.preferredFontDescriptor(withTextStyle: .body)
return UIFont(descriptor: descriptor, size: size)
case .monospaced:
return UIFont.monospacedSystemFont(ofSize: size, weight: .regular)
}
}
}
// MARK: -
/// EPUB
@@ -21,6 +66,8 @@ public struct RDEPUBReaderConfiguration: Equatable {
public var fontSize: CGFloat
/// 1.6 1.6
public var lineHeightMultiple: CGFloat
///
public var fontChoice: RDEPUBReaderFontChoice
///
public var numberOfColumns: Int
/// 20pt
@@ -50,6 +97,10 @@ public struct RDEPUBReaderConfiguration: Equatable {
/// // .light
public var theme: RDEPUBReaderTheme
///
public var darkImageAdjustmentEnabled: Bool
/// 0 0.12 ~ 0.2
public var darkImageBlendRatio: CGFloat
///
public var fixedLayoutFit: RDEPUBFixedLayoutFit
/// //
@@ -63,6 +114,7 @@ public struct RDEPUBReaderConfiguration: Equatable {
/// - Parameters:
/// - fontSize: 15pt
/// - lineHeightMultiple: 1.6
/// - fontChoice:
/// - displayType: .pageCurl
/// - landscapeDualPageEnabled: true
/// - showsTableOfContents: true
@@ -71,12 +123,15 @@ public struct RDEPUBReaderConfiguration: Equatable {
/// - reflowableContentInsets:
/// - fixedContentInset:
/// - theme: .light
/// - darkImageAdjustmentEnabled:
/// - darkImageBlendRatio:
/// - fixedLayoutFit:
/// - fixedLayoutSpreadMode:
/// - textRenderingEngine:
public init(
fontSize: CGFloat = 15,
lineHeightMultiple: CGFloat = 1.6,
fontChoice: RDEPUBReaderFontChoice = .system,
numberOfColumns: Int = 1,
columnGap: CGFloat = 20,
displayType: RDReaderView.DisplayType = .pageCurl,
@@ -87,12 +142,15 @@ public struct RDEPUBReaderConfiguration: Equatable {
reflowableContentInsets: UIEdgeInsets = UIEdgeInsets(top: 40, left: 16, bottom: 40, right: 16),
fixedContentInset: UIEdgeInsets = .zero,
theme: RDEPUBReaderTheme = .light,
darkImageAdjustmentEnabled: Bool = true,
darkImageBlendRatio: CGFloat = 0.15,
fixedLayoutFit: RDEPUBFixedLayoutFit = .page,
fixedLayoutSpreadMode: RDEPUBFixedLayoutSpreadMode = .automatic,
textRenderingEngine: RDEPUBTextRenderingEngine = .dtCoreText
) {
self.fontSize = fontSize
self.lineHeightMultiple = lineHeightMultiple
self.fontChoice = fontChoice
self.numberOfColumns = max(1, numberOfColumns)
self.columnGap = max(0, columnGap)
self.displayType = displayType
@@ -103,6 +161,8 @@ public struct RDEPUBReaderConfiguration: Equatable {
self.reflowableContentInsets = reflowableContentInsets
self.fixedContentInset = fixedContentInset
self.theme = theme
self.darkImageAdjustmentEnabled = darkImageAdjustmentEnabled
self.darkImageBlendRatio = max(0, min(0.35, darkImageBlendRatio))
self.fixedLayoutFit = fixedLayoutFit
self.fixedLayoutSpreadMode = fixedLayoutSpreadMode
self.textRenderingEngine = textRenderingEngine