86 lines
2.7 KiB
Swift
86 lines
2.7 KiB
Swift
import Foundation
|
||
|
||
struct RDEPUBChapterWindowSnapshot {
|
||
/// 窗口中的章节(有序:prev, current, next)
|
||
let chapters: [RDEPUBRuntimeChapter]
|
||
|
||
/// 展平后的连续页数组(供 RDReaderView 消费)
|
||
/// 窗口内页码不写回 RDEPUBTextPage 模型;
|
||
/// flattenedPages 的数组下标就是窗口内连续页码(从 0 开始)。
|
||
let flattenedPages: [RDEPUBTextPage]
|
||
|
||
/// 当前章在 chapters 数组中的索引
|
||
let anchorChapterIndex: Int
|
||
|
||
/// 当前章在 flattenedPages 中的起始页码(从 0 开始,窗口内编号)
|
||
let anchorPageOffset: Int
|
||
|
||
/// 当前窗口首章的 spineIndex,用于调试日志和跨窗口映射
|
||
let windowStartSpineIndex: Int
|
||
|
||
// MARK: - 构建
|
||
|
||
/// 从章节窗口构建快照
|
||
static func from(
|
||
currentChapter: RDEPUBRuntimeChapter,
|
||
previousChapter: RDEPUBRuntimeChapter?,
|
||
nextChapter: RDEPUBRuntimeChapter?
|
||
) -> RDEPUBChapterWindowSnapshot {
|
||
var chapters: [RDEPUBRuntimeChapter] = []
|
||
var anchorIndex = 0
|
||
var pageOffset = 0
|
||
|
||
if let prev = previousChapter {
|
||
chapters.append(prev)
|
||
anchorIndex = 1
|
||
pageOffset = prev.pages.count
|
||
}
|
||
|
||
chapters.append(currentChapter)
|
||
|
||
if let next = nextChapter {
|
||
chapters.append(next)
|
||
}
|
||
|
||
// 展平页数组
|
||
var allPages: [RDEPUBTextPage] = []
|
||
for (chIdx, ch) in chapters.enumerated() {
|
||
for var page in ch.pages {
|
||
page.chapterIndex = chIdx
|
||
allPages.append(page)
|
||
}
|
||
}
|
||
|
||
let windowStartSpineIndex = chapters.first?.spineIndex ?? currentChapter.spineIndex
|
||
|
||
return RDEPUBChapterWindowSnapshot(
|
||
chapters: chapters,
|
||
flattenedPages: allPages,
|
||
anchorChapterIndex: anchorIndex,
|
||
anchorPageOffset: pageOffset,
|
||
windowStartSpineIndex: windowStartSpineIndex
|
||
)
|
||
}
|
||
|
||
// MARK: - 查询
|
||
|
||
/// 窗口内页码(即 flattenedPages 下标)-> 所属章节
|
||
func chapterForPage(flattenedPageIndex: Int) -> RDEPUBRuntimeChapter? {
|
||
var offset = 0
|
||
for ch in chapters {
|
||
if flattenedPageIndex < offset + ch.pages.count {
|
||
return ch
|
||
}
|
||
offset += ch.pages.count
|
||
}
|
||
return nil
|
||
}
|
||
|
||
/// 窗口内页码(即 flattenedPages 下标)-> 所属章节的 spineIndex
|
||
func spineIndexForPage(flattenedPageIndex: Int) -> Int? {
|
||
return chapterForPage(flattenedPageIndex: flattenedPageIndex)?.spineIndex
|
||
}
|
||
|
||
/// 总页数(窗口内)
|
||
var pageCount: Int { flattenedPages.count }
|
||
} |