feat: add in-reader search and restructure documentation
- Add RDEPUBReaderSearchBarView with animated show/hide, keyword navigation, and match counting integrated into the reader controller - Restructure docs: replace scattered design docs with consolidated BUSINESS_LOGIC.md and UML_CLASS_DIAGRAMS.md; update ARCHITECTURE.md - Add SearchTests and FanrenParseTimeTest; enhance LargeBookOnDemandTests - Add scripts/run_ui_regression.sh and summarize_ui_results.py for automated UI test execution and reporting Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
d20196ee34
commit
0e7c0577e3
@@ -52,6 +52,7 @@ final class RDEPUBReaderRuntime {
|
||||
context.readingSession = nil
|
||||
context.textBook = nil
|
||||
context.bookPageMap = nil
|
||||
context.pendingFullPageMap = nil
|
||||
context.activeBookmarks = []
|
||||
context.activeHighlights = []
|
||||
context.searchState = nil
|
||||
@@ -312,31 +313,37 @@ final class RDEPUBReaderRuntime {
|
||||
}
|
||||
|
||||
func refreshBookPageMapInPlace(_ bookPageMap: RDEPUBBookPageMap) {
|
||||
guard let readerView = context.readerView,
|
||||
// 暂存完整 map,等用户下次导航时再应用,避免当前阅读位置跳转
|
||||
// 此时保留旧 map,用户看到的内容和页码完全不变
|
||||
context.pendingFullPageMap = bookPageMap
|
||||
}
|
||||
|
||||
/// 用户导航时检查并应用待处理的完整 BookPageMap
|
||||
func applyPendingFullPageMapIfNeeded() {
|
||||
guard let pendingMap = context.pendingFullPageMap,
|
||||
let readerView = context.readerView,
|
||||
let controller = context.controller else { return }
|
||||
|
||||
let currentPage = max(readerView.currentPage, 0)
|
||||
context.pendingFullPageMap = nil
|
||||
|
||||
// 保存当前位置(在旧 map 下解析)
|
||||
let currentLocation = locationCoordinator.currentVisibleLocation()
|
||||
|
||||
// 替换 map 和快照
|
||||
context.textBook = nil
|
||||
context.bookPageMap = bookPageMap
|
||||
context.replaceActiveSnapshot(makeSnapshot(from: bookPageMap))
|
||||
context.bookPageMap = pendingMap
|
||||
context.replaceActiveSnapshot(makeSnapshot(from: pendingMap))
|
||||
|
||||
// 仅刷新总页数,不重建页面内容(避免后台元数据解析期间刷新掉用户选区)
|
||||
readerView.reloadPageCountOnly()
|
||||
|
||||
// 用户正在选区或正在滑动翻页时跳过页面跳转,避免打断交互
|
||||
let cv = readerView.collectionView
|
||||
let isUserInteracting = cv.isTracking || cv.isDragging || cv.isDecelerating
|
||||
if context.currentSelection == nil, !isUserInteracting, bookPageMap.totalPages > 0 {
|
||||
let maxValidPage = max(bookPageMap.totalPages - 1, 0)
|
||||
if currentPage > maxValidPage {
|
||||
readerView.transitionToPage(pageNum: maxValidPage, animated: false)
|
||||
}
|
||||
}
|
||||
// 用位置在新 map 中重新解析正确的页码
|
||||
if let currentLocation {
|
||||
locationCoordinator.persist(location: currentLocation)
|
||||
} else if let resolvedLocation = controller.resolvedTextLocation(forPageNumber: currentPage + 1) {
|
||||
locationCoordinator.persist(location: resolvedLocation)
|
||||
let newPageNumber = controller.pageNumber(for: currentLocation) ?? (readerView.currentPage + 1)
|
||||
let newPage = max(0, newPageNumber - 1)
|
||||
readerView.reloadPageCountOnly()
|
||||
if newPage != readerView.currentPage {
|
||||
readerView.transitionToPage(pageNum: newPage, animated: false)
|
||||
}
|
||||
} else {
|
||||
readerView.reloadPageCountOnly()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -530,6 +537,7 @@ final class RDEPUBReaderRuntime {
|
||||
func clearOnDemandPageModeState() {
|
||||
chapterRuntimeStore.invalidateAllForSettingsChange()
|
||||
context.bookPageMap = nil
|
||||
context.pendingFullPageMap = nil
|
||||
}
|
||||
|
||||
private func makeSnapshot(from bookPageMap: RDEPUBBookPageMap) -> RDEPUBReadingSession.PaginationSnapshot {
|
||||
|
||||
Reference in New Issue
Block a user