- 拆分 ContentDelegates/TextContentView 为独立协调器(InteractionCoordinator、LocationResolution、ExternalLinks、AttachmentTooltip) - 新增 RDEPUBAttachmentTooltipView/OverlayView 附件气泡提示 - 新增 RDEPUBDarkImageAdjuster 暗色模式图片亮度适配 - 新增 RDEPUBSelectionLoupeView 选区放大镜 - 新增 MetadataParseWorker/CancellationController 元数据解析取消机制 - 重构 PresentationRuntime/PaginationCoordinator 精简职责 - 优化 ChapterLoader/WarmupOrchestrator 异步章节加载 - CFI 模块微调与 NoteModels 更新 - 清理冗余文档,更新架构/UML/业务逻辑文档 Co-Authored-By: Claude <noreply@anthropic.com>
40 lines
1.2 KiB
Swift
40 lines
1.2 KiB
Swift
import Foundation
|
|
|
|
public struct RDEPUBCFIPath: Codable, Equatable, Hashable {
|
|
|
|
public var steps: [RDEPUBCFIStep]
|
|
|
|
public init(steps: [RDEPUBCFIStep] = []) {
|
|
self.steps = steps
|
|
}
|
|
|
|
public func commonPrefix(with other: RDEPUBCFIPath) -> RDEPUBCFIPath {
|
|
var prefix: [RDEPUBCFIStep] = []
|
|
let upperBound = min(steps.count, other.steps.count)
|
|
for index in 0..<upperBound {
|
|
guard steps[index] == other.steps[index] else { break }
|
|
prefix.append(steps[index])
|
|
}
|
|
return RDEPUBCFIPath(steps: prefix)
|
|
}
|
|
|
|
public func droppingPrefix(_ prefix: RDEPUBCFIPath) -> RDEPUBCFIPath {
|
|
guard prefix.steps.count <= steps.count else { return self }
|
|
let candidate = Array(steps.prefix(prefix.steps.count))
|
|
guard candidate == prefix.steps else { return self }
|
|
return RDEPUBCFIPath(steps: Array(steps.dropFirst(prefix.steps.count)))
|
|
}
|
|
}
|
|
|
|
public struct RDEPUBCFIStep: Codable, Equatable, Hashable {
|
|
|
|
public var index: Int
|
|
|
|
public var idAssertion: String?
|
|
|
|
public init(index: Int, idAssertion: String? = nil) {
|
|
self.index = index
|
|
self.idAssertion = idAssertion?.rd_nilIfEmpty
|
|
}
|
|
}
|