source dump of claude code
at main 75 lines 2.5 kB view raw
1import { useRef } from 'react' 2 3// Hook to handle the transition to red when tokens stop flowing. 4// Driven by the parent's animation clock time instead of independent intervals, 5// so it slows down when the terminal is blurred. 6export function useStalledAnimation( 7 time: number, 8 currentResponseLength: number, 9 hasActiveTools = false, 10 reducedMotion = false, 11): { 12 isStalled: boolean 13 stalledIntensity: number 14} { 15 const lastTokenTime = useRef(time) 16 const lastResponseLength = useRef(currentResponseLength) 17 const mountTime = useRef(time) 18 const stalledIntensityRef = useRef(0) 19 const lastSmoothTime = useRef(time) 20 21 // Reset timer when new tokens arrive (check actual length change) 22 if (currentResponseLength > lastResponseLength.current) { 23 lastTokenTime.current = time 24 lastResponseLength.current = currentResponseLength 25 stalledIntensityRef.current = 0 26 lastSmoothTime.current = time 27 } 28 29 // Derive time since last token from animation clock 30 let timeSinceLastToken: number 31 if (hasActiveTools) { 32 timeSinceLastToken = 0 33 lastTokenTime.current = time 34 } else if (currentResponseLength > 0) { 35 timeSinceLastToken = time - lastTokenTime.current 36 } else { 37 timeSinceLastToken = time - mountTime.current 38 } 39 40 // Calculate stalled intensity based on time since last token 41 // Start showing red after 3 seconds of no new tokens (only when no tools are active) 42 const isStalled = timeSinceLastToken > 3000 && !hasActiveTools 43 const intensity = isStalled 44 ? Math.min((timeSinceLastToken - 3000) / 2000, 1) // Fade over 2 seconds 45 : 0 46 47 // Smooth intensity transition driven by animation frame ticks 48 if (!reducedMotion && (intensity > 0 || stalledIntensityRef.current > 0)) { 49 const dt = time - lastSmoothTime.current 50 if (dt >= 50) { 51 const steps = Math.floor(dt / 50) 52 let current = stalledIntensityRef.current 53 for (let i = 0; i < steps; i++) { 54 const diff = intensity - current 55 if (Math.abs(diff) < 0.01) { 56 current = intensity 57 break 58 } 59 current += diff * 0.1 60 } 61 stalledIntensityRef.current = current 62 lastSmoothTime.current = time 63 } 64 } else { 65 stalledIntensityRef.current = intensity 66 lastSmoothTime.current = time 67 } 68 69 // When reducedMotion is enabled, use instant intensity change 70 const effectiveIntensity = reducedMotion 71 ? intensity 72 : stalledIntensityRef.current 73 74 return { isStalled, stalledIntensity: effectiveIntensity } 75}