Stabilize WebGL title and timeline texture flow

This commit is contained in:
2026-06-17 08:31:46 +02:00
parent ef358c5cfd
commit c19ebe3089
5 changed files with 211 additions and 76 deletions
+48 -8
View File
@@ -39,6 +39,7 @@ class BookPlaybackTimelineModule extends BaseModule {
'waitForVisualCompletion',
'waitForRevealCommit',
'requestPageFlip',
'prepareFlipPlan',
'waitForPageFlipFinished',
'prewarmSegmentTextures',
'getPageMetaForIndex',
@@ -361,6 +362,11 @@ class BookPlaybackTimelineModule extends BaseModule {
const startedAt = Number(segment.revealStartedAt)
|| await (segment.revealStartedPromise || Promise.resolve(performance.now()));
const duration = this.getRightRevealDurationMs(segment);
segment.plannedRightRevealDurationMs = duration;
this.recordDiagnostic('wait-right-reveal-planned', {
...segment,
plannedRightRevealDurationMs: duration
});
const elapsed = Math.max(0, performance.now() - Number(startedAt || performance.now()));
const remaining = Math.max(0, duration - elapsed);
const planned = new Promise(resolve => {
@@ -413,13 +419,7 @@ class BookPlaybackTimelineModule extends BaseModule {
async requestPageFlip(direction = 1, options = {}) {
if (this.isChoiceAwaitingPlayer()) return false;
await this.pageCache?.prewarmNavigationWindow?.({
currentSpread: this.getVisibleSpreadIndex(),
targetSpread: options.targetSpread,
endSpread: Math.max(0, Number(this.pagination?.spreads?.length || 1) - 1),
getPageMetaForIndex: this.getPageMetaForIndex,
recordMiss: false
});
const flipPlan = await this.prepareFlipPlan(direction, options);
await this.assertSegmentReady({
blockId: options.blockId ?? null,
targetSpreadIndex: options.targetSpread,
@@ -432,11 +432,48 @@ class BookPlaybackTimelineModule extends BaseModule {
window.BookLabDebug.requestPageFlip(direction, {
force: options.force === true,
reason: options.reason || 'timeline',
targetSpread: options.targetSpread
targetSpread: options.targetSpread,
prewarm: flipPlan.prewarm,
flipPlan
});
return wait;
}
async prepareFlipPlan(direction = 1, options = {}) {
const currentSpread = this.getVisibleSpreadIndex();
const targetSpread = Number.isFinite(Number(options.targetSpread))
? Math.max(0, Math.round(Number(options.targetSpread)))
: Math.max(0, currentSpread + Math.sign(Number(direction || 0)));
const prewarm = await this.pageCache?.prewarmNavigationWindow?.({
currentSpread,
targetSpread,
endSpread: Math.max(0, Number(this.pagination?.spreads?.length || 1) - 1),
getPageMetaForIndex: this.getPageMetaForIndex,
recordMiss: false
});
const sourceSide = direction > 0 ? 'right' : 'left';
const backSide = direction > 0 ? 'left' : 'right';
const sourcePageIndex = currentSpread * 2 + (sourceSide === 'right' ? 1 : 0);
const backPageIndex = targetSpread * 2 + (backSide === 'right' ? 1 : 0);
const plan = {
direction,
currentSpread,
targetSpread,
sourceSide,
backSide,
sourcePageMeta: this.getPageMetaForIndex(sourcePageIndex),
backPageMeta: this.getPageMetaForIndex(backPageIndex),
prewarm,
createdAt: performance.now()
};
this.markBenchmark('flip-plan-ready', plan);
this.recordDiagnostic('flip-plan-ready', {
...plan,
targetSpreadIndex: targetSpread
});
return plan;
}
async prewarmSegmentTextures(segment = {}) {
if (!this.pageCache || typeof this.pageCache.prewarmNavigationWindow !== 'function') return null;
const targetSpread = Math.max(0, Number(segment.targetSpreadIndex || 0));
@@ -604,6 +641,9 @@ class BookPlaybackTimelineModule extends BaseModule {
spreadIndex: segment.targetSpreadIndex ?? null,
status: segment.status || null,
revealSides: Array.isArray(segment.revealSides) ? segment.revealSides : [],
plannedRightRevealDurationMs: Number.isFinite(Number(segment.plannedRightRevealDurationMs))
? Math.round(Number(segment.plannedRightRevealDurationMs))
: undefined,
at: Math.round(performance.now())
});
while (this.timelineDiagnostics.length > 200) this.timelineDiagnostics.shift();