Checkpoint before line-grid scrolling refactor
This commit is contained in:
@@ -9,10 +9,11 @@ class SocketClientModule extends BaseModule {
|
||||
super('socket-client', 'Socket Client');
|
||||
|
||||
// Dependencies
|
||||
this.dependencies = ['text-buffer', 'markup-parser'];
|
||||
this.dependencies = ['text-buffer', 'markup-parser', 'story-history'];
|
||||
|
||||
this.socket = null;
|
||||
this.textBuffer = null;
|
||||
this.storyHistory = null;
|
||||
this.isConnected = false;
|
||||
this.reconnectAttempts = 0;
|
||||
this.maxReconnectAttempts = 5;
|
||||
@@ -20,6 +21,8 @@ class SocketClientModule extends BaseModule {
|
||||
this.url = null;
|
||||
this.eventListeners = {};
|
||||
this.defaultHost = 'localhost:3000';
|
||||
this.receivedBlockCounter = 0;
|
||||
this.receivedParagraphCounter = 0;
|
||||
|
||||
// Bind methods using parent's bindMethods utility
|
||||
this.bindMethods([
|
||||
@@ -44,6 +47,8 @@ class SocketClientModule extends BaseModule {
|
||||
'setupGameEventHandlers',
|
||||
'processTurnResult',
|
||||
'processParagraphResult',
|
||||
'storeAndQueueBlocks',
|
||||
'normalizeHistoryBlock',
|
||||
'dispatchTurnTags',
|
||||
'isTimedCueTag',
|
||||
'cueMarkersFromTags',
|
||||
@@ -93,6 +98,11 @@ class SocketClientModule extends BaseModule {
|
||||
console.error("Socket Client: Failed to get text-buffer module");
|
||||
return false;
|
||||
}
|
||||
this.storyHistory = this.getModule('story-history');
|
||||
if (!this.storyHistory) {
|
||||
console.error("Socket Client: Failed to get story-history module");
|
||||
return false;
|
||||
}
|
||||
|
||||
this.reportProgress(50, "Setting up connection parameters");
|
||||
|
||||
@@ -191,7 +201,7 @@ class SocketClientModule extends BaseModule {
|
||||
});
|
||||
}
|
||||
|
||||
processTurnResult(data) {
|
||||
async processTurnResult(data) {
|
||||
if (!data) return;
|
||||
|
||||
const turnId = Number(data.turnId);
|
||||
@@ -199,6 +209,10 @@ class SocketClientModule extends BaseModule {
|
||||
console.error('Socket Client: Invalid TurnResult received', data);
|
||||
return;
|
||||
}
|
||||
if (turnId === 1) {
|
||||
this.receivedBlockCounter = 0;
|
||||
this.receivedParagraphCounter = 0;
|
||||
}
|
||||
|
||||
if (Array.isArray(data.globalTags) && data.globalTags.length > 0) {
|
||||
document.dispatchEvent(new CustomEvent('story:global-tags', {
|
||||
@@ -214,12 +228,24 @@ class SocketClientModule extends BaseModule {
|
||||
role: null,
|
||||
cueTags: []
|
||||
};
|
||||
const turnBlocks = [];
|
||||
data.paragraphs.forEach((paragraph) => {
|
||||
pendingParagraph = this.processParagraphResult(paragraph, turnId, pendingParagraph);
|
||||
const result = this.processParagraphResult(paragraph, turnId, pendingParagraph);
|
||||
pendingParagraph = result.pendingParagraph;
|
||||
turnBlocks.push(...result.blocks);
|
||||
});
|
||||
|
||||
this.dispatchChoices(Array.isArray(data.choices) ? data.choices : []);
|
||||
this.dispatchInputMode(data.inputMode || (Array.isArray(data.choices) && data.choices.length > 0 ? 'choice' : 'text'));
|
||||
await this.storeAndQueueBlocks(turnBlocks);
|
||||
|
||||
const choices = Array.isArray(data.choices) ? data.choices : [];
|
||||
const inputMode = data.inputMode || (choices.length > 0 ? 'choice' : 'text');
|
||||
this.dispatchChoices(choices);
|
||||
this.dispatchInputMode(inputMode);
|
||||
if (turnBlocks.length === 0 && choices.length > 0) {
|
||||
document.dispatchEvent(new CustomEvent('story:process-state', {
|
||||
detail: { state: 'ready', reason: 'choice-only-turn', turnId }
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
dispatchTurnTags(tags, paragraph = null) {
|
||||
@@ -259,15 +285,16 @@ class SocketClientModule extends BaseModule {
|
||||
const immediateTags = tags.filter(tag => !this.isStructuralTag(tag) && !this.isTimedCueTag(tag));
|
||||
|
||||
this.dispatchTurnTags(immediateTags, paragraph);
|
||||
blocks.forEach(block => this.enqueueStructuredBlock(block));
|
||||
|
||||
if (!text) {
|
||||
return {
|
||||
role: paragraphRole || pending.role || null,
|
||||
cueTags: [
|
||||
...(Array.isArray(pending.cueTags) ? pending.cueTags : []),
|
||||
...cueTags
|
||||
]
|
||||
blocks,
|
||||
pendingParagraph: {
|
||||
role: paragraphRole || pending.role || null,
|
||||
cueTags: [
|
||||
...(Array.isArray(pending.cueTags) ? pending.cueTags : []),
|
||||
...cueTags
|
||||
]
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -279,7 +306,7 @@ class SocketClientModule extends BaseModule {
|
||||
...cueTags
|
||||
])
|
||||
];
|
||||
this.enqueueStructuredBlock({
|
||||
blocks.push({
|
||||
type: 'paragraph',
|
||||
text,
|
||||
layoutText: paragraph.layoutText || text,
|
||||
@@ -291,7 +318,50 @@ class SocketClientModule extends BaseModule {
|
||||
turnId
|
||||
});
|
||||
|
||||
return { role: null, cueTags: [] };
|
||||
return { blocks, pendingParagraph: { role: null, cueTags: [] } };
|
||||
}
|
||||
|
||||
async storeAndQueueBlocks(blocks = []) {
|
||||
if (!Array.isArray(blocks) || blocks.length === 0) return;
|
||||
|
||||
if (!this.storyHistory) {
|
||||
this.storyHistory = this.getModule('story-history');
|
||||
}
|
||||
|
||||
const normalizedBlocks = blocks.map(block => this.normalizeHistoryBlock(block));
|
||||
let records = normalizedBlocks;
|
||||
if (this.storyHistory && typeof this.storyHistory.recordBlocks === 'function') {
|
||||
records = await this.storyHistory.recordBlocks(normalizedBlocks);
|
||||
document.dispatchEvent(new CustomEvent('story:history-updated', {
|
||||
detail: {
|
||||
gameId: this.storyHistory.currentGameId || null,
|
||||
latestBlockId: this.storyHistory.nextBlockId - 1
|
||||
}
|
||||
}));
|
||||
} else {
|
||||
console.warn('Socket Client: Story history unavailable; queueing unstored blocks');
|
||||
}
|
||||
|
||||
records.forEach(block => this.enqueueStructuredBlock(block));
|
||||
}
|
||||
|
||||
normalizeHistoryBlock(block) {
|
||||
const type = String(block?.type || 'paragraph');
|
||||
this.receivedBlockCounter += 1;
|
||||
const normalized = {
|
||||
...block,
|
||||
type,
|
||||
id: block.id || `${type}-${block.turnId || 'turn'}-${this.receivedBlockCounter}`
|
||||
};
|
||||
|
||||
if (type === 'paragraph') {
|
||||
normalized.paragraphIndex = Number.isInteger(block.paragraphIndex)
|
||||
? block.paragraphIndex
|
||||
: this.receivedParagraphCounter;
|
||||
this.receivedParagraphCounter += 1;
|
||||
}
|
||||
|
||||
return normalized;
|
||||
}
|
||||
|
||||
isStructuralTag(tag) {
|
||||
|
||||
Reference in New Issue
Block a user