Stabilize WebGL book pagination restore
This commit is contained in:
@@ -19,11 +19,16 @@ class BookPaginationModule extends BaseModule {
|
||||
this.latestBlockId = 0;
|
||||
this.latestRenderedBlockId = 0;
|
||||
this.appliedPageReserveBlocks = new Set();
|
||||
this.preparedBlockCache = new Map();
|
||||
|
||||
this.bindMethods([
|
||||
'initialize',
|
||||
'refreshFromHistory',
|
||||
'preparePendingBlock',
|
||||
'getPreparedBlockCacheKey',
|
||||
'rememberPreparedBlock',
|
||||
'takePreparedBlock',
|
||||
'clearPreparedBlocks',
|
||||
'buildSpreads',
|
||||
'buildPages',
|
||||
'buildSpreadsFromPages',
|
||||
@@ -86,6 +91,10 @@ class BookPaginationModule extends BaseModule {
|
||||
this.setCurrentSpread(this.currentSpreadIndex + direction);
|
||||
}
|
||||
});
|
||||
this.pages = this.buildPages([]);
|
||||
this.spreads = this.buildSpreadsFromPages(this.pages);
|
||||
this.currentSpreadIndex = 0;
|
||||
this.publish({ reason: 'initial-title-spread', allowFutureUnrendered: true });
|
||||
this.reportProgress(100, 'Book pagination ready');
|
||||
return true;
|
||||
}
|
||||
@@ -93,11 +102,13 @@ class BookPaginationModule extends BaseModule {
|
||||
handlePageCountChanged(event) {
|
||||
this.pageFormat?.setPageCount?.(event.detail?.pageCount);
|
||||
this.metrics = this.pageFormat.getTextureMetrics(this.pageFormat.getTextureWidth?.());
|
||||
this.clearPreparedBlocks();
|
||||
this.refreshFromHistory();
|
||||
}
|
||||
|
||||
async refreshFromHistory(event = null) {
|
||||
const token = ++this.refreshToken;
|
||||
this.clearPreparedBlocks();
|
||||
const detail = event?.detail || {};
|
||||
const gameId = detail.gameId || this.storyHistory?.currentGameId || null;
|
||||
const latestRenderedBlockId = Math.max(
|
||||
@@ -117,7 +128,7 @@ class BookPaginationModule extends BaseModule {
|
||||
this.latestRenderedBlockId = 0;
|
||||
this.currentSpreadIndex = 0;
|
||||
this.appliedPageReserveBlocks.clear();
|
||||
this.publish();
|
||||
this.publish({ reason: 'empty-history' });
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -135,7 +146,7 @@ class BookPaginationModule extends BaseModule {
|
||||
: renderedSpreadIndex >= 0
|
||||
? renderedSpreadIndex
|
||||
: Math.max(0, Math.min(this.currentSpreadIndex, Math.max(0, this.spreads.length - 1)));
|
||||
this.publish();
|
||||
this.publish({ reason: 'history-refresh', allowFutureUnrendered: true });
|
||||
}
|
||||
|
||||
getContinuationBlockId(latestBlockId = 0, latestRenderedBlockId = 0) {
|
||||
@@ -158,6 +169,31 @@ class BookPaginationModule extends BaseModule {
|
||||
const historyEndBlockId = options.includeUnrenderedHistory
|
||||
? Math.max(0, pendingBlockId - 1)
|
||||
: latestRenderedBlockId;
|
||||
const cacheKey = this.getPreparedBlockCacheKey(gameId, pendingBlockId, historyEndBlockId, latestRenderedBlockId, options);
|
||||
const cached = options.activate !== false ? this.takePreparedBlock(cacheKey) : null;
|
||||
if (cached) {
|
||||
this.latestBlockId = pendingBlockId;
|
||||
this.latestRenderedBlockId = latestRenderedBlockId;
|
||||
this.pages = cached.pages;
|
||||
this.spreads = cached.spreads;
|
||||
this.currentSpreadIndex = cached.targetSpread
|
||||
? cached.targetSpread.index
|
||||
: Math.max(0, Math.min(this.currentSpreadIndex, Math.max(0, this.spreads.length - 1)));
|
||||
if (options.publish !== false) this.publish({ reason: 'prepared-cache-activate' });
|
||||
document.dispatchEvent(new CustomEvent('book-pagination:block-prepared', {
|
||||
detail: {
|
||||
blockId: pendingBlockId,
|
||||
spread: cached.targetSpread || this.getCurrentSpread(),
|
||||
spreadIndex: cached.targetSpread?.index ?? this.currentSpreadIndex,
|
||||
latestBlockId: pendingBlockId,
|
||||
latestRenderedBlockId,
|
||||
preloadOnly: false,
|
||||
reusedPreparedPagination: true
|
||||
}
|
||||
}));
|
||||
return cached.targetSpread || this.getCurrentSpread();
|
||||
}
|
||||
|
||||
const historyBlocks = historyEndBlockId > 0
|
||||
? await this.storyHistory.getBlocksRange(gameId, 1, historyEndBlockId)
|
||||
: [];
|
||||
@@ -181,6 +217,13 @@ class BookPaginationModule extends BaseModule {
|
||||
const lines = Array.isArray(spread?.[side]) ? spread[side] : [];
|
||||
return lines.some(line => Number(line?.blockId || 0) === pendingBlockId);
|
||||
}));
|
||||
if (options.activate === false) {
|
||||
this.rememberPreparedBlock(cacheKey, {
|
||||
pages: preparedPages,
|
||||
spreads: preparedSpreads,
|
||||
targetSpread: targetSpread || null
|
||||
});
|
||||
}
|
||||
if (options.activate !== false) {
|
||||
this.latestBlockId = pendingBlockId;
|
||||
this.latestRenderedBlockId = latestRenderedBlockId;
|
||||
@@ -189,7 +232,7 @@ class BookPaginationModule extends BaseModule {
|
||||
this.currentSpreadIndex = Math.max(0, Math.min(this.spreads.length - 1, this.currentSpreadIndex));
|
||||
if (targetSpread) this.currentSpreadIndex = targetSpread.index;
|
||||
}
|
||||
if (options.publish !== false) this.publish();
|
||||
if (options.publish !== false) this.publish({ reason: options.activate === false ? 'prepare-preload' : 'prepare-activate' });
|
||||
document.dispatchEvent(new CustomEvent('book-pagination:block-prepared', {
|
||||
detail: {
|
||||
blockId: pendingBlockId,
|
||||
@@ -203,6 +246,39 @@ class BookPaginationModule extends BaseModule {
|
||||
return targetSpread || (options.activate === false ? preparedSpreads[0] : this.getCurrentSpread());
|
||||
}
|
||||
|
||||
getPreparedBlockCacheKey(gameId, blockId, historyEndBlockId, latestRenderedBlockId, options = {}) {
|
||||
const includeUnrendered = options.includeUnrenderedHistory === true ? 'unrendered' : 'rendered';
|
||||
return [
|
||||
gameId || 'game',
|
||||
Math.max(0, Number(blockId || 0)),
|
||||
Math.max(0, Number(historyEndBlockId || 0)),
|
||||
Math.max(0, Number(latestRenderedBlockId || 0)),
|
||||
includeUnrendered,
|
||||
this.metrics?.width || 0,
|
||||
this.metrics?.height || 0
|
||||
].join(':');
|
||||
}
|
||||
|
||||
rememberPreparedBlock(key, prepared) {
|
||||
if (!key || !prepared?.pages || !prepared?.spreads) return;
|
||||
this.preparedBlockCache.set(key, prepared);
|
||||
while (this.preparedBlockCache.size > 12) {
|
||||
const oldestKey = this.preparedBlockCache.keys().next().value;
|
||||
this.preparedBlockCache.delete(oldestKey);
|
||||
}
|
||||
}
|
||||
|
||||
takePreparedBlock(key) {
|
||||
if (!key || !this.preparedBlockCache.has(key)) return null;
|
||||
const prepared = this.preparedBlockCache.get(key);
|
||||
this.preparedBlockCache.delete(key);
|
||||
return prepared;
|
||||
}
|
||||
|
||||
clearPreparedBlocks() {
|
||||
this.preparedBlockCache.clear();
|
||||
}
|
||||
|
||||
buildSpreads(blocks = []) {
|
||||
this.pages = this.buildPages(blocks);
|
||||
return this.buildSpreadsFromPages(this.pages);
|
||||
@@ -891,11 +967,11 @@ class BookPaginationModule extends BaseModule {
|
||||
|
||||
setCurrentSpread(index = 0) {
|
||||
this.currentSpreadIndex = Math.max(0, Math.min(Math.round(Number(index || 0)), Math.max(0, this.spreads.length - 1)));
|
||||
this.publish();
|
||||
this.publish({ reason: 'set-current-spread', allowFutureUnrendered: true });
|
||||
return this.currentSpreadIndex;
|
||||
}
|
||||
|
||||
publish() {
|
||||
publish(options = {}) {
|
||||
const writtenPageLimit = Math.max(0, (Math.max(0, this.spreads.length - 1) * 2) - 1);
|
||||
document.dispatchEvent(new CustomEvent('book-pagination:spread-updated', {
|
||||
detail: {
|
||||
@@ -904,7 +980,9 @@ class BookPaginationModule extends BaseModule {
|
||||
spreadCount: this.spreads.length,
|
||||
writtenPageLimit,
|
||||
latestBlockId: this.latestBlockId,
|
||||
latestRenderedBlockId: this.latestRenderedBlockId
|
||||
latestRenderedBlockId: this.latestRenderedBlockId,
|
||||
reason: options.reason || 'publish',
|
||||
allowFutureUnrendered: options.allowFutureUnrendered === true
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user