Skip to content

Commit 8c1cc78

Browse files
fix: add ability to see all previous rounds in broadcast
1 parent adc6c15 commit 8c1cc78

4 files changed

Lines changed: 121 additions & 11 deletions

File tree

src/api/lichess/broadcasts.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,45 @@ export const getLichessBroadcasts = async (): Promise<Broadcast[]> => {
6868
})
6969
}
7070

71+
export const getLichessBroadcastById = async (
72+
broadcastId: string,
73+
): Promise<Broadcast | null> => {
74+
try {
75+
console.log('Fetching broadcast by ID:', broadcastId)
76+
const response = await fetch(
77+
`https://lichess.org/api/broadcast/${broadcastId}`,
78+
{
79+
headers: {
80+
Accept: 'application/json',
81+
},
82+
},
83+
)
84+
85+
if (!response.ok) {
86+
console.error(`Failed to fetch broadcast: ${response.status}`)
87+
return null
88+
}
89+
90+
const data = await response.json()
91+
console.log('Broadcast data received:', {
92+
name: data.tour?.name,
93+
rounds: data.rounds?.length,
94+
roundNames: data.rounds?.map((r: any) => r.name),
95+
})
96+
97+
// Validate that this looks like broadcast data
98+
if (data.tour && data.rounds) {
99+
return data as Broadcast
100+
}
101+
102+
console.error('Invalid broadcast data structure')
103+
return null
104+
} catch (error) {
105+
console.error('Error fetching broadcast by ID:', error)
106+
return null
107+
}
108+
}
109+
71110
export const getLichessTopBroadcasts =
72111
async (): Promise<TopBroadcastsResponse> => {
73112
const response = await fetch('https://lichess.org/api/broadcast/top', {

src/hooks/useBroadcastController.ts

Lines changed: 80 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
} from 'src/types'
1515
import {
1616
getLichessBroadcasts,
17+
getLichessBroadcastById,
1718
getLichessTopBroadcasts,
1819
convertTopBroadcastToBroadcast,
1920
getBroadcastRoundPGN,
@@ -145,6 +146,17 @@ export const useBroadcastController = (): BroadcastStreamController => {
145146
}
146147

147148
setBroadcastSections(sections)
149+
console.log(
150+
'Loaded broadcasts:',
151+
sections.map((s) => ({
152+
title: s.title,
153+
broadcasts: s.broadcasts.map((b) => ({
154+
name: b.tour.name,
155+
rounds: b.rounds.length,
156+
roundNames: b.rounds.map((r) => r.name),
157+
})),
158+
})),
159+
)
148160
setBroadcastState((prev) => ({ ...prev, isConnecting: false }))
149161
} catch (error) {
150162
console.error('Error loading broadcasts:', error)
@@ -158,14 +170,44 @@ export const useBroadcastController = (): BroadcastStreamController => {
158170
}, [])
159171

160172
const selectBroadcast = useCallback(
161-
(broadcastId: string) => {
162-
// Find broadcast across all sections
173+
async (broadcastId: string) => {
174+
console.log('Selecting broadcast:', broadcastId)
175+
176+
// Always fetch complete broadcast data directly from API to ensure we get ALL rounds
177+
// The /api/broadcast endpoint often only returns currently ongoing rounds
163178
let broadcast: Broadcast | undefined
164-
for (const section of broadcastSections) {
165-
broadcast = section.broadcasts.find((b) => b.tour.id === broadcastId)
166-
if (broadcast) break
179+
try {
180+
console.log('Fetching complete broadcast data from API...')
181+
const fetchedBroadcast = await getLichessBroadcastById(broadcastId)
182+
if (fetchedBroadcast) {
183+
broadcast = fetchedBroadcast
184+
console.log('✓ Got complete broadcast data with all rounds')
185+
}
186+
} catch (error) {
187+
console.error('Failed to get broadcast by ID:', error)
188+
}
189+
190+
// Fallback: use data from sections if API call failed
191+
if (!broadcast) {
192+
console.log('API call failed, falling back to section data...')
193+
for (const section of broadcastSections) {
194+
broadcast = section.broadcasts.find((b) => b.tour.id === broadcastId)
195+
if (broadcast) {
196+
console.log('⚠ Found in sections but may have incomplete rounds')
197+
break
198+
}
199+
}
167200
}
201+
168202
if (broadcast) {
203+
console.log(
204+
'Selected broadcast:',
205+
broadcast.tour.name,
206+
'with',
207+
broadcast.rounds.length,
208+
'rounds:',
209+
broadcast.rounds.map((r) => r.name),
210+
)
169211
setCurrentBroadcast(broadcast)
170212
// Auto-select default round if available
171213
const defaultRound =
@@ -175,6 +217,8 @@ export const useBroadcastController = (): BroadcastStreamController => {
175217
if (defaultRound) {
176218
setCurrentRound(defaultRound)
177219
}
220+
} else {
221+
console.error('Broadcast not found:', broadcastId)
178222
}
179223
},
180224
[broadcastSections],
@@ -185,11 +229,33 @@ export const useBroadcastController = (): BroadcastStreamController => {
185229
if (currentBroadcast) {
186230
const round = currentBroadcast.rounds.find((r) => r.id === roundId)
187231
if (round) {
188-
setCurrentRound(round)
232+
console.log('Selecting round:', round.name, `(${roundId})`)
233+
189234
// Stop current stream if different round
190235
if (currentRoundId.current !== roundId) {
191-
stopRoundStream()
236+
console.log('Switching to different round, stopping current stream')
237+
// Stop the current stream
238+
if (abortController.current) {
239+
abortController.current.abort()
240+
abortController.current = null
241+
}
242+
setBroadcastState((prev) => ({
243+
...prev,
244+
isConnected: false,
245+
isLive: false,
246+
}))
247+
currentRoundId.current = null
248+
gameStates.current.clear()
249+
lastPGNData.current = ''
250+
251+
// Clear current game selection when switching rounds
252+
setCurrentGame(null)
253+
// Clear round data so games list shows loading state
254+
setRoundData(null)
192255
}
256+
257+
setCurrentRound(round)
258+
// The useEffect will automatically start streaming the new round
193259
}
194260
}
195261
},
@@ -557,13 +623,18 @@ export const useBroadcastController = (): BroadcastStreamController => {
557623
}
558624
}, [startRoundStream])
559625

560-
// Auto-start stream when round is selected and ongoing
626+
// Auto-start stream when any round is selected
561627
useEffect(() => {
562628
if (
563-
currentRound?.ongoing &&
629+
currentRound &&
564630
!broadcastState.isConnecting &&
565631
!broadcastState.isConnected
566632
) {
633+
console.log(
634+
'Starting stream for selected round:',
635+
currentRound.name,
636+
currentRound.ongoing ? '(Live)' : '(Past/Future)',
637+
)
567638
startRoundStream(currentRound.id)
568639
}
569640
}, [

src/pages/broadcast/[broadcastId]/[roundId].tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ const BroadcastAnalysisPage: NextPage = () => {
6464
}
6565

6666
// Select broadcast and round
67-
broadcastController.selectBroadcast(broadcastId)
67+
await broadcastController.selectBroadcast(broadcastId)
6868
broadcastController.selectRound(roundId)
6969

7070
setLoading(false)

src/types/broadcast/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ export interface BroadcastStreamController {
116116
roundData: BroadcastRoundData | null
117117
broadcastState: BroadcastState
118118
loadBroadcasts: () => Promise<void>
119-
selectBroadcast: (broadcastId: string) => void
119+
selectBroadcast: (broadcastId: string) => Promise<void>
120120
selectRound: (roundId: string) => void
121121
selectGame: (gameId: string) => void
122122
startRoundStream: (roundId: string) => void

0 commit comments

Comments
 (0)