全量换表前用旧页表回环验证当前位置
初始 partial 窗口被全书页表接管时,live 页码(窗口坐标)与新表解析 页码(全书坐标)不可比,±1 启发式误判后 preserveLivePage 会把模型 位置钉在全书第 1 页,导致位置错乱并级联阻塞后续全表提交。改为换表 前先用旧表解析 currentLocation:回环等于 live 页说明位置忠实反映 屏幕内容,换表后无条件信任新表解析结果;不等时才退回 ±1 门槛,保留 对 stale 持久化位置的防护。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
bd6e915fbd
commit
5ae7823ef8
@ -160,6 +160,11 @@ final class RDEPUBPresentationRuntime {
|
||||
) {
|
||||
let currentLocation = locationCoordinator.currentVisibleLocation()
|
||||
let livePageBeforeApply = readerView.currentPage + 1
|
||||
// Resolved against the outgoing page map. When it round-trips to the live
|
||||
// page, the location faithfully describes what is on screen, so whatever
|
||||
// page it resolves to in the new map is authoritative even if the two maps
|
||||
// number pages differently (partial-window -> full-book takeover).
|
||||
let oldResolvedPage = currentLocation.flatMap { controller.pageNumber(for: $0) }
|
||||
|
||||
context.textBook = nil
|
||||
applyPageMapToLiveModel(newPageMap)
|
||||
@ -172,11 +177,12 @@ final class RDEPUBPresentationRuntime {
|
||||
let resolvedTargetPage = controller.pageNumber(for: currentLocation)
|
||||
let shouldTrustResolvedLocation = shouldTrustFullReplaceResolvedPage(
|
||||
resolvedTargetPage,
|
||||
livePageBeforeApply: livePageBeforeApply
|
||||
livePageBeforeApply: livePageBeforeApply,
|
||||
locationMatchesLivePage: oldResolvedPage == livePageBeforeApply
|
||||
)
|
||||
RDEPUBBackgroundTrace.log(
|
||||
"Reconciliation",
|
||||
"applyFullPageMapReplacement decision livePage=\(livePageBeforeApply) resolvedTargetPage=\(resolvedTargetPage ?? -1) trustResolved=\(shouldTrustResolvedLocation) href=\(currentLocation.href)"
|
||||
"applyFullPageMapReplacement decision livePage=\(livePageBeforeApply) oldResolvedPage=\(oldResolvedPage ?? -1) resolvedTargetPage=\(resolvedTargetPage ?? -1) trustResolved=\(shouldTrustResolvedLocation) href=\(currentLocation.href)"
|
||||
)
|
||||
|
||||
if shouldTrustResolvedLocation,
|
||||
@ -433,9 +439,16 @@ final class RDEPUBPresentationRuntime {
|
||||
|
||||
private func shouldTrustFullReplaceResolvedPage(
|
||||
_ resolvedTargetPage: Int?,
|
||||
livePageBeforeApply: Int
|
||||
livePageBeforeApply: Int,
|
||||
locationMatchesLivePage: Bool
|
||||
) -> Bool {
|
||||
guard let resolvedTargetPage else { return false }
|
||||
if locationMatchesLivePage {
|
||||
return true
|
||||
}
|
||||
// The location did not round-trip to the live page in the outgoing map
|
||||
// (stale persisted location or mid-transition), so only follow it when it
|
||||
// stays next to the page the user is actually looking at.
|
||||
return abs(resolvedTargetPage - livePageBeforeApply) <= 1
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user