Skip to content

Commit d8da9b2

Browse files
fix: loading issues
1 parent 630faad commit d8da9b2

File tree

4 files changed

+95
-67
lines changed

4 files changed

+95
-67
lines changed

src/api/lichess/streaming.ts

Lines changed: 41 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ export const getLichessTVGame = async () => {
4141
const data = await res.json()
4242

4343
// Return the best game (highest rated players)
44-
const bestChannel = data.best
44+
const bestChannel = data.rapid
4545
if (!bestChannel?.gameId) {
4646
throw new Error('No TV game available')
4747
}
@@ -79,24 +79,55 @@ export const streamLichessGame = async (
7979
},
8080
})
8181

82+
let gameStarted = false
83+
8284
const onMessage = (message: any) => {
8385
console.log('Raw message received:', message)
8486

8587
if (message.id) {
8688
// This is the initial game state with full game info
8789
console.log('Game start message:', message)
8890
onGameStart(message)
91+
gameStarted = true
8992
} else if (message.uci || message.lm) {
9093
// This is a move - handle both formats: {"fen":"...", "uci":"e2e4"} or {"fen":"...", "lm":"e2e4"}
94+
// If we haven't received the initial game state yet, trigger game start with a minimal state
95+
if (!gameStarted) {
96+
console.log(
97+
'First move received without initial game state, creating minimal game',
98+
)
99+
onGameStart({
100+
id: gameId, // Use the gameId we're streaming
101+
players: {
102+
white: { user: { name: 'White' } },
103+
black: { user: { name: 'Black' } },
104+
},
105+
fen: message.fen,
106+
})
107+
gameStarted = true
108+
}
109+
91110
onMove({
92111
fen: message.fen,
93112
uci: message.uci || message.lm,
94113
wc: message.wc,
95114
bc: message.bc,
96115
})
97116
} else if (message.fen && !message.uci && !message.lm) {
98-
// This is the initial position - ignore this message
117+
// This is the initial position - could be the first message for a starting game
99118
console.log('Initial position received:', message)
119+
if (!gameStarted) {
120+
console.log('Initial position message, creating game')
121+
onGameStart({
122+
id: gameId,
123+
players: {
124+
white: { user: { name: 'White' } },
125+
black: { user: { name: 'Black' } },
126+
},
127+
fen: message.fen,
128+
})
129+
gameStarted = true
130+
}
100131
} else {
101132
console.log('Unknown message format:', message)
102133
}
@@ -128,24 +159,23 @@ export const streamLichessGame = async (
128159
export const createAnalyzedGameFromLichessStream = (
129160
gameData: any,
130161
): AnalyzedGame => {
131-
const { players, fen, id } = gameData
162+
const { players, id } = gameData
132163

133164
const whitePlayer: Player = {
134-
name: players.white?.user?.name || 'White',
135-
rating: players.white?.rating,
165+
name: players?.white?.user?.name || 'White',
166+
rating: players?.white?.rating,
136167
}
137168

138169
const blackPlayer: Player = {
139-
name: players.black?.user?.name || 'Black',
140-
rating: players.black?.rating,
170+
name: players?.black?.user?.name || 'Black',
171+
rating: players?.black?.rating,
141172
}
142173

143-
// Use the current FEN from the game data (this is the current position)
174+
// Use the starting position as our tree root - we'll build moves incrementally
144175
const startingFen = 'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1'
145-
const currentFen = fen || startingFen
146176

147-
// Build moves array - start with just the initial position
148-
// We'll build up the game tree as moves come in via the stream
177+
// Build moves array with just the initial position for now
178+
// Moves will be added as they come in via the stream
149179
const gameStates = [
150180
{
151181
board: startingFen,
@@ -156,25 +186,6 @@ export const createAnalyzedGameFromLichessStream = (
156186
},
157187
]
158188

159-
// If we have the current position FEN and it's different from starting position,
160-
// we know the game is in progress, but we don't have the move history
161-
if (currentFen !== startingFen) {
162-
// Game is in progress - we'll show the current position
163-
// but we won't have move history until new moves come in
164-
gameStates.push({
165-
board: currentFen,
166-
lastMove: gameData.lastMove
167-
? ([gameData.lastMove.slice(0, 2), gameData.lastMove.slice(2, 4)] as [
168-
string,
169-
string,
170-
])
171-
: undefined,
172-
san: gameData.lastMove || '', // We don't have SAN notation from Lichess stream initially
173-
check: false as const,
174-
maia_values: {},
175-
})
176-
}
177-
178189
// Create game tree starting from the beginning
179190
const tree = new GameTree(startingFen)
180191

src/components/Analysis/StreamAnalysis.tsx

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -127,17 +127,16 @@ export const StreamAnalysis: React.FC<Props> = ({
127127
if (!playedMove) return
128128

129129
// Check for promotions in available moves
130-
const availableMoves = Array.from(
131-
analysisController.availableMoves.entries(),
132-
).flatMap(([from, tos]) =>
133-
(tos as string[]).map((to: string) => ({ from, to })),
134-
)
130+
const availableMoves: { from: string; to: string }[] = []
131+
for (const [from, tos] of analysisController.availableMoves.entries()) {
132+
for (const to of tos as string[]) {
133+
availableMoves.push({ from, to })
134+
}
135+
}
135136

136-
const matching = availableMoves.filter(
137-
(m: { from: string; to: string }) => {
138-
return m.from === playedMove[0] && m.to === playedMove[1]
139-
},
140-
)
137+
const matching = availableMoves.filter((m) => {
138+
return m.from === playedMove[0] && m.to === playedMove[1]
139+
})
141140

142141
if (matching.length > 1) {
143142
// Multiple matching moves (i.e. promotion)
@@ -177,6 +176,9 @@ export const StreamAnalysis: React.FC<Props> = ({
177176
return chess.turn() === 'w' ? 'white' : 'black'
178177
}, [analysisController.currentNode])
179178

179+
// Check if we're using dummy game data (waiting for real game data)
180+
const isWaitingForGameData = game.id === ''
181+
180182
// Stream status component
181183
const StreamStatus = () => (
182184
<div className="mb-2 flex items-center justify-between rounded bg-background-1 px-4 py-2">
@@ -191,13 +193,15 @@ export const StreamAnalysis: React.FC<Props> = ({
191193
}`}
192194
/>
193195
<span className="text-sm font-medium">
194-
{streamState.isLive
195-
? 'LIVE'
196-
: streamState.isConnected
197-
? 'Connected'
198-
: streamState.error
199-
? 'Disconnected'
200-
: 'Connecting...'}
196+
{isWaitingForGameData && streamState.isConnected
197+
? 'Waiting for game data...'
198+
: streamState.isLive
199+
? 'LIVE'
200+
: streamState.isConnected
201+
? 'Connected'
202+
: streamState.error
203+
? 'Disconnected'
204+
: 'Connecting...'}
201205
</span>
202206
{streamState.error && (
203207
<span className="text-xs text-red-400">({streamState.error})</span>

src/hooks/useLichessStreamController.ts

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ export const useLichessStreamController = (): LichessStreamController => {
8181
...prev,
8282
gameStarted: true,
8383
isLive: true,
84+
isConnected: true, // Set connected as soon as we receive game data
85+
isConnecting: false,
8486
error: null,
8587
}))
8688

@@ -116,6 +118,16 @@ export const useLichessStreamController = (): LichessStreamController => {
116118

117119
const newGame = createAnalyzedGameFromLichessStream(minimalGameData)
118120

121+
// Set stream as connected since we're receiving data
122+
setStreamState((prev) => ({
123+
...prev,
124+
isConnected: true,
125+
isConnecting: false,
126+
gameStarted: true,
127+
isLive: true,
128+
error: null,
129+
}))
130+
119131
// Try to parse the current move
120132
try {
121133
return parseLichessStreamMove(moveData, newGame)
@@ -179,6 +191,7 @@ export const useLichessStreamController = (): LichessStreamController => {
179191

180192
try {
181193
// Start streaming directly - the stream API will handle invalid game IDs
194+
// Note: isConnected will be set when we receive the first data (in handleGameStart or handleMove)
182195
await streamLichessGame(
183196
gameId,
184197
handleGameStart,
@@ -187,11 +200,8 @@ export const useLichessStreamController = (): LichessStreamController => {
187200
abortController.current.signal,
188201
)
189202

190-
setStreamState((prev) => ({
191-
...prev,
192-
isConnected: true,
193-
isConnecting: false,
194-
}))
203+
// Stream completed normally - this happens when the game ends or connection closes
204+
console.log('Stream completed')
195205
} catch (error) {
196206
console.error('Stream error:', error)
197207

src/pages/analysis/stream/[gameId].tsx

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -94,16 +94,19 @@ const StreamAnalysisPage: NextPage = () => {
9494
}
9595
}, [streamController.game, analysisController])
9696

97-
if (!isReady || !gameId) {
98-
return (
99-
<DelayedLoading isLoading={true}>
100-
<div></div>
101-
</DelayedLoading>
102-
)
103-
}
104-
105-
// Show loading while connecting or if no game data yet
106-
if (streamController.streamState.isConnecting || !streamController.game) {
97+
// if (!isReady || !gameId) {
98+
// return (
99+
// <DelayedLoading isLoading={true}>
100+
// <div></div>
101+
// </DelayedLoading>
102+
// )
103+
// }
104+
105+
// Show loading only while actively connecting AND no data has been received yet
106+
if (
107+
streamController.streamState.isConnecting &&
108+
!streamController.streamState.gameStarted
109+
) {
107110
return (
108111
<>
109112
<Head>
@@ -147,12 +150,12 @@ const StreamAnalysisPage: NextPage = () => {
147150
<>
148151
<Head>
149152
<title>
150-
Live Analysis: {streamController.game.whitePlayer.name} vs{' '}
151-
{streamController.game.blackPlayer.name} – Maia Chess
153+
Live Analysis: {streamController.game?.whitePlayer.name || 'Unknown'}{' '}
154+
vs {streamController.game?.blackPlayer.name || 'Unknown'} – Maia Chess
152155
</title>
153156
<meta
154157
name="description"
155-
content={`Watch live analysis of ${streamController.game.whitePlayer.name} vs ${streamController.game.blackPlayer.name} with real-time Maia AI insights.`}
158+
content={`Watch live analysis of ${streamController.game?.whitePlayer.name || 'Unknown'} vs ${streamController.game?.blackPlayer.name || 'Unknown'} with real-time Maia AI insights.`}
156159
/>
157160
</Head>
158161

@@ -168,9 +171,9 @@ const StreamAnalysisPage: NextPage = () => {
168171
</AnimatePresence>
169172

170173
<TreeControllerContext.Provider value={analysisController}>
171-
{streamController.game && analysisController && (
174+
{analysisController && (
172175
<StreamAnalysis
173-
game={streamController.game}
176+
game={streamController.game || dummyGame}
174177
streamState={streamController.streamState}
175178
onReconnect={streamController.reconnect}
176179
onStopStream={streamController.stopStream}

0 commit comments

Comments
 (0)