Refine line-based story scrolling
This commit is contained in:
@@ -34,8 +34,9 @@ class StoryHistoryModule extends BaseModule {
|
||||
'hasSaveSlot',
|
||||
'getSaveSlots',
|
||||
'getBlocks',
|
||||
'getBlock',
|
||||
'getBlocksRange',
|
||||
'getWindowForTurn',
|
||||
'getFirstBlockForTurn',
|
||||
'getRenderedLineCount',
|
||||
'findBlockForLine',
|
||||
'clearGame',
|
||||
@@ -145,12 +146,12 @@ class StoryHistoryModule extends BaseModule {
|
||||
});
|
||||
if (!record) return null;
|
||||
|
||||
const lineCount = Math.max(1, Number(metrics.lineCount || record.lineCount || 1));
|
||||
const previousLineCount = Number(record.lineCount || 0);
|
||||
const hadLineStart = Number.isFinite(Number(record.lineStart));
|
||||
const lineStart = hadLineStart
|
||||
? Math.max(0, Number(record.lineStart))
|
||||
: this.renderedLineCount;
|
||||
const lineCount = Math.max(0, Number(metrics.lineCount ?? record.lineCount ?? 1));
|
||||
const lineStart = Number.isFinite(Number(metrics.lineStart))
|
||||
? Math.max(0, Number(metrics.lineStart))
|
||||
: Number.isFinite(Number(record.lineStart))
|
||||
? Math.max(0, Number(record.lineStart))
|
||||
: this.renderedLineCount;
|
||||
|
||||
const updated = {
|
||||
...record,
|
||||
@@ -159,11 +160,7 @@ class StoryHistoryModule extends BaseModule {
|
||||
metricsUpdatedAt: Date.now()
|
||||
};
|
||||
|
||||
if (!hadLineStart) {
|
||||
this.renderedLineCount = Math.max(this.renderedLineCount, lineStart + lineCount);
|
||||
} else if (lineStart + previousLineCount >= this.renderedLineCount) {
|
||||
this.renderedLineCount = Math.max(lineStart + lineCount, this.renderedLineCount + (lineCount - previousLineCount));
|
||||
}
|
||||
this.renderedLineCount = Math.max(this.renderedLineCount, lineStart + lineCount);
|
||||
|
||||
await new Promise((resolve, reject) => {
|
||||
const request = this.tx(this.historyStore, 'readwrite').put(updated);
|
||||
@@ -235,6 +232,16 @@ class StoryHistoryModule extends BaseModule {
|
||||
});
|
||||
}
|
||||
|
||||
getBlock(gameId = this.currentGameId, blockId = null) {
|
||||
if (!this.db || !gameId || blockId == null) return Promise.resolve(null);
|
||||
const id = Math.max(1, Number(blockId || 1));
|
||||
return new Promise((resolve, reject) => {
|
||||
const request = this.tx(this.historyStore).get(`${gameId}:${id}`);
|
||||
request.onsuccess = () => resolve(request.result || null);
|
||||
request.onerror = () => reject(request.error);
|
||||
});
|
||||
}
|
||||
|
||||
getBlocksRange(gameId = this.currentGameId, startBlockId = 1, endBlockId = Infinity) {
|
||||
if (!this.db || !gameId) return Promise.resolve([]);
|
||||
const start = Math.max(1, Number(startBlockId || 1));
|
||||
@@ -259,9 +266,9 @@ class StoryHistoryModule extends BaseModule {
|
||||
});
|
||||
}
|
||||
|
||||
async getWindowForTurn(gameId = this.currentGameId, turnId, visibleLimit = this.visibleLimit) {
|
||||
if (!this.db || !gameId || turnId == null) return { blocks: [], targetBlockId: null };
|
||||
const target = await new Promise((resolve, reject) => {
|
||||
async getFirstBlockForTurn(gameId = this.currentGameId, turnId) {
|
||||
if (!this.db || !gameId || turnId == null) return null;
|
||||
return new Promise((resolve, reject) => {
|
||||
const index = this.tx(this.historyStore).index('gameId');
|
||||
const request = index.openCursor(IDBKeyRange.only(gameId), 'next');
|
||||
request.onsuccess = () => {
|
||||
@@ -278,15 +285,6 @@ class StoryHistoryModule extends BaseModule {
|
||||
};
|
||||
request.onerror = () => reject(request.error);
|
||||
});
|
||||
|
||||
if (!target?.blockId) return { blocks: [], targetBlockId: null };
|
||||
const latest = Math.max(0, this.nextBlockId - 1);
|
||||
const limit = Math.max(1, Number(visibleLimit || this.visibleLimit));
|
||||
const halfBefore = Math.floor(limit / 2);
|
||||
const maxStart = Math.max(1, latest - limit + 1);
|
||||
const start = Math.max(1, Math.min(maxStart, target.blockId - halfBefore));
|
||||
const blocks = await this.getBlocksRange(gameId, start, Math.min(latest, start + limit - 1));
|
||||
return { blocks, targetBlockId: target.blockId };
|
||||
}
|
||||
|
||||
async getRenderedLineCount(gameId = this.currentGameId, latestRenderedBlockId = this.latestRenderedBlockId) {
|
||||
|
||||
Reference in New Issue
Block a user