Stabilize WebGL book pagination restore

This commit is contained in:
2026-06-09 16:42:12 +02:00
parent fe51410a3b
commit 171cafeb65
7 changed files with 315 additions and 85 deletions
+44 -11
View File
@@ -1074,14 +1074,31 @@ class UIDisplayHandlerModule extends BaseModule {
publish: false,
includeUnrenderedHistory: true
});
const previewRevealDetail = {
id: sentence.id,
blockId: sentence.blockId,
wordTimings: sentence.animation?.wordTimings || [],
cueTimings: sentence.animation?.cueTimings || [],
totalDuration: sentence.animation?.totalDuration || 0,
spread: previewSpread,
preloadOnly: true
};
if (previewSpread && typeof bookTextureRenderer.prepareRevealBlock === 'function') {
bookTextureRenderer.prepareRevealBlock(previewRevealDetail, { preloadOnly: true });
}
if (Number(previewSpread?.index || 0) > currentSpreadIndex) {
await this.waitForWebGLPageFlip({
const flipped = await this.waitForWebGLPageFlip({
direction: 1,
reason: 'pending-block-overflow',
targetSpread: previewSpread.index
});
if (!flipped) {
throw new Error(`WebGL book page flip did not start for prepared spread ${previewSpread.index}`);
}
}
preparedSpread = await bookPagination.preparePendingBlock(sentence);
preparedSpread = await bookPagination.preparePendingBlock(sentence, {
includeUnrenderedHistory: true
});
} else {
document.dispatchEvent(new CustomEvent('book-pagination:prepare-block', {
detail: {
@@ -1110,23 +1127,39 @@ class UIDisplayHandlerModule extends BaseModule {
waitForWebGLPageFlip(detail = {}) {
return new Promise((resolve) => {
let resolved = false;
const finish = () => {
const cleanup = () => {
window.clearTimeout(timeout);
document.removeEventListener('webgl-book:page-flip-started', onStarted);
document.removeEventListener('webgl-book:page-flip-finished', onFinished);
};
const finish = (result) => {
if (resolved) return;
resolved = true;
window.clearTimeout(timeout);
document.removeEventListener('webgl-book:page-flip-finished', finish);
resolve(true);
cleanup();
resolve(result);
};
const timeout = window.setTimeout(finish, 1400);
document.addEventListener('webgl-book:page-flip-finished', finish, { once: true });
const requestedTargetSpread = Number.isFinite(Number(detail.targetSpread))
? Math.max(0, Math.round(Number(detail.targetSpread)))
: null;
const matchesTarget = (eventDetail = {}) => requestedTargetSpread == null
|| Math.max(0, Math.round(Number(eventDetail.targetSpread || 0))) === requestedTargetSpread;
const onStarted = (event) => {
if (!matchesTarget(event.detail || {})) return;
document.documentElement.dataset.webglLastStartedPageFlip = JSON.stringify(event.detail || {});
};
const onFinished = (event) => {
if (!matchesTarget(event.detail || {})) return;
finish(true);
};
const timeout = window.setTimeout(() => finish(false), 2400);
document.addEventListener('webgl-book:page-flip-started', onStarted);
document.addEventListener('webgl-book:page-flip-finished', onFinished);
document.dispatchEvent(new CustomEvent('webgl-book:request-page-flip', {
detail: {
direction: Math.sign(Number(detail.direction || 1)) || 1,
reason: detail.reason || 'pending-block-overflow',
force: true,
targetSpread: Number.isFinite(Number(detail.targetSpread))
? Math.max(0, Math.round(Number(detail.targetSpread)))
: null
targetSpread: requestedTargetSpread
}
}));
});