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 } }