ReadViewSDK/Sources/RDReaderView/EPUBCore/RDEPUBModels.swift
shenlei d5a7755702 feat: 支持加密 EPUB、试读墙、工具栏定制与朝向锁定
- 新增 RDEPUBResourceDataProvider 解密钩子协议 + 访问登记表,收敛章节 HTML/
  图片/内联 CSS/脚注/封面/图片查看器/正文取图等读取点,scheme handler 对加密书
  禁用流式分支;新增 RDEPUBDecryptingImageAttachment 解密 DTCoreText 图片附件;
  RDEPUBReaderDependencies.live(resourceDataProvider:) 便捷注入。明文书零影响。
- 试读墙:configuration.trialPolicy + delegate epubReaderTrialWallView/
  DidReachTrialWall,UI 由宿主提供(RDEPUBReaderController+Trial)。
- 工具栏定制:RDEPUBReaderTop/BottomToolViewProtocol 协议 + dependencies 工厂注入,
  内置栏已 conform,configureTopToolView 改协议类型。
- 朝向锁定:RDEPUBMetadata.orientation(OPF rendition:orientation 主,
  iBooks display-options 兜底)+ RDEPUBReaderController+Orientation 重写支持朝向、
  打开后主动转向。

注:RDEPUBReaderController+LocationResolution / PaginationCoordinator 为本次改动前
即存在的工作区修改,一并纳入。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-10 12:25:17 +09:00

214 lines
5.0 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import Foundation
public enum RDEPUBLayout: String, Codable {
case reflowable
case fixed
}
public enum RDEPUBReadingProfile: String, Codable {
case webInteractive
case webFixedLayout
case textReflowable
}
public enum RDEPUBReadingProgression: String, Codable {
case ltr
case rtl
case auto
}
public enum RDEPUBPageSpread: String, Codable {
case left
case right
case center
}
/// EPUB rendition:orientation / iBooks display-options
public enum RDEPUBOrientation: String, Codable {
case portrait
case landscape
case auto
}
public struct RDEPUBMetadata: Codable, Equatable {
public var identifier: String?
public var title: String
public var author: String?
public var language: String?
public var version: String?
public var layout: RDEPUBLayout
public var spread: String?
public var readingProgression: RDEPUBReadingProgression
/// nil =
/// OPF rendition:orientation > META-INF/com.apple.ibooks.display-options.xml
public var orientation: RDEPUBOrientation?
public init(
identifier: String? = nil,
title: String = "",
author: String? = nil,
language: String? = nil,
version: String? = nil,
layout: RDEPUBLayout = .reflowable,
spread: String? = nil,
readingProgression: RDEPUBReadingProgression = .auto,
orientation: RDEPUBOrientation? = nil
) {
self.identifier = identifier
self.title = title
self.author = author
self.language = language
self.version = version
self.layout = layout
self.spread = spread
self.readingProgression = readingProgression
self.orientation = orientation
}
}
public struct RDEPUBManifestItem: Codable, Equatable {
public var id: String
public var href: String
public var mediaType: String
public var properties: [String]
public var fallback: String?
public var mediaOverlay: String?
public var title: String?
public init(
id: String,
href: String,
mediaType: String,
properties: [String] = [],
fallback: String? = nil,
mediaOverlay: String? = nil,
title: String? = nil
) {
self.id = id
self.href = href
self.mediaType = mediaType
self.properties = properties
self.fallback = fallback
self.mediaOverlay = mediaOverlay
self.title = title
}
public var isNavigationDocument: Bool {
properties.contains("nav")
}
public var isNCX: Bool {
mediaType == "application/x-dtbncx+xml"
}
}
public struct RDEPUBSpineItem: Codable, Equatable {
public var idref: String
public var href: String
public var mediaType: String
public var title: String
public var linear: Bool
public var properties: [String]
public var pageSpread: RDEPUBPageSpread?
public var layout: RDEPUBLayout?
public init(
idref: String,
href: String,
mediaType: String,
title: String,
linear: Bool = true,
properties: [String] = [],
pageSpread: RDEPUBPageSpread? = nil,
layout: RDEPUBLayout? = nil
) {
self.idref = idref
self.href = href
self.mediaType = mediaType
self.title = title
self.linear = linear
self.properties = properties
self.pageSpread = pageSpread
self.layout = layout
}
}
public struct EPUBTableOfContentsItem: Codable, Equatable {
public var title: String
public var href: String
public var children: [EPUBTableOfContentsItem]
public init(title: String, href: String, children: [EPUBTableOfContentsItem] = []) {
self.title = title
self.href = href
self.children = children
}
}
public enum RDEPUBParserError: LocalizedError {
case archiveOpenFailed(URL)
case missingContainerXML
case missingRootFile
case invalidRootFilePath(String)
case invalidXML(URL)
case missingManifestItem(idref: String)
case emptySpine
case invalidArchiveEntryPath(String)
public var errorDescription: String? {
switch self {
case .archiveOpenFailed(let url):
return "无法打开 EPUB 压缩包: \(url.lastPathComponent)"
case .missingContainerXML:
return "EPUB 缺少 META-INF/container.xml"
case .missingRootFile:
return "container.xml 中未找到 rootfile"
case .invalidRootFilePath(let path):
return "OPF 路径无效: \(path)"
case .invalidXML(let url):
return "XML 解析失败: \(url.lastPathComponent)"
case .missingManifestItem(let idref):
return "spine itemref 找不到对应 manifest 项: \(idref)"
case .emptySpine:
return "OPF spine 为空"
case .invalidArchiveEntryPath(let path):
return "归档条目路径非法: \(path)"
}
}
}