Reuse spanning-aware prepared plan at activate (kill pre-playback pause)
A spanning block stalled ~2.1s before it began playing: activate ran prepareRevealBlock with forceRebuild, synchronously redrawing the start spread (and preloading the continuation spread) on the main thread, because the lookahead plan had been built with right-only timing before pagination committed the overflow. Build the start-spread plan spanning-aware during lookahead instead: when the preview layout shows the block overflows, derive its timing across both preview spreads (via the revealSpreadSourceOverride) and cache it. activate then reuses that plan — the same fast cached-plan path non-spanning blocks already use — with no synchronous redraw. forceRebuild is kept only as a fallback when a block spans but was not prepared spanning-aware (e.g. an immediate prepare with no preview layout), and an evicted plan still rebuilds correctly because pagination is committed by then. Verified live: the spanning block's pre-playback gap dropped from ~2088ms to 139ms (equal to non-spanning blocks), while the right line still reveals over its area share (~3.3s), the continuation still animates from the start, and there are no fast-forwards or problems. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -916,17 +916,30 @@ class BookTextureRendererModule extends BaseModule {
|
||||
this.revealPublishBlockIds = new Set([id]);
|
||||
const spread = detail.spread || this.currentSpread || this.pagination?.getCurrentSpread?.();
|
||||
const sides = ['left', 'right'];
|
||||
const published = this.drawSpread(spread, sides, {
|
||||
phase,
|
||||
publishEvent: options.publishEvent !== false
|
||||
});
|
||||
this.preloadAdditionalRevealSpreads(id, spread);
|
||||
// When the caller supplies the (not-yet-committed) preview spreads for a spanning
|
||||
// block, derive this spread's reveal timing across all of them so the cached plan
|
||||
// already spans both pages. activate can then reuse it instead of forcing a
|
||||
// synchronous rebuild on the critical path.
|
||||
const spanningPreview = Array.isArray(detail.previewSpreads) && detail.previewSpreads.length > 1;
|
||||
const previousOverride = this.revealSpreadSourceOverride;
|
||||
if (spanningPreview) this.revealSpreadSourceOverride = detail.previewSpreads;
|
||||
let published = null;
|
||||
try {
|
||||
published = this.drawSpread(spread, sides, {
|
||||
phase,
|
||||
publishEvent: options.publishEvent !== false
|
||||
});
|
||||
} finally {
|
||||
this.revealSpreadSourceOverride = previousOverride;
|
||||
}
|
||||
if (!spanningPreview) this.preloadAdditionalRevealSpreads(id, spread);
|
||||
if (phase === 'prepare' && published) {
|
||||
this.pageCache?.rememberPreparedRevealPlan?.(id, {
|
||||
...published,
|
||||
blockId,
|
||||
wordTimings,
|
||||
totalDuration: detail.totalDuration || 0
|
||||
totalDuration: detail.totalDuration || 0,
|
||||
spanningTimingPrepared: spanningPreview === true
|
||||
});
|
||||
}
|
||||
this.markPipelineTiming('prepareRevealBlock:end', {
|
||||
|
||||
Reference in New Issue
Block a user