Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 26x 26x 26x 1x 1x 1x 1x 1x 1x 1x 1x 20x 20x 20x 20x 20x 20x 20x 20x 20x 20x 20x 20x 20x 20x 19x 19x 20x 1x 1x 1x 18x 18x 20x 5x 5x 5x 5x 5x 20x 20x | 'use client'
import { useEffect, useRef } from 'react'
import { useTTS } from '@/hooks/useTTS'
import { GAME_BREAK_ANNOUNCEMENT_CLIPS, PICK_A_GAME } from '@/lib/audio/clips/practice'
type GameBreakPhase = 'initializing' | 'auto-starting' | 'selecting' | 'playing' | 'completed'
interface UseGameBreakAudioOptions {
phase: GameBreakPhase
isVisible: boolean
}
function pickRandom<T>(arr: readonly T[]): T {
return arr[Math.floor(Math.random() * arr.length)]
}
/**
* Speaks game break cues on phase transitions.
*
* - initializing → auto-starting: random game break announcement
* - initializing → selecting: announcement + "Pick a game!" after delay
*/
export function useGameBreakAudio({ phase, isVisible }: UseGameBreakAudioOptions) {
const prevPhaseRef = useRef<GameBreakPhase>(phase)
const sayAnnouncement = useTTS(pickRandom(GAME_BREAK_ANNOUNCEMENT_CLIPS), {
tone: 'celebration',
})
const sayPickAGame = useTTS(PICK_A_GAME, {
tone: 'tutorial-instruction',
})
useEffect(() => {
const prevPhase = prevPhaseRef.current
prevPhaseRef.current = phase
if (!isVisible) return
// initializing → auto-starting: announce the game break
if (prevPhase === 'initializing' && phase === 'auto-starting') {
sayAnnouncement(pickRandom(GAME_BREAK_ANNOUNCEMENT_CLIPS))
return
}
// initializing → selecting: announce + pick a game after a short delay
if (prevPhase === 'initializing' && phase === 'selecting') {
sayAnnouncement(pickRandom(GAME_BREAK_ANNOUNCEMENT_CLIPS)).then(() => {
sayPickAGame()
})
return
}
}, [phase, isVisible, sayAnnouncement, sayPickAGame])
}
|