Download src/components/Spinner/useStalledAnimation.ts from chenbhao/codev: direct link, hf CLI and curl.
- Browser
- Download file 2.5 kB
-
https://huggingface.co/chenbhao/codev/resolve/afbc7edaae4e6bb0102ba024b49ce8be89d2264c/src/components/Spinner/useStalledAnimation.ts
- Command line
-
hf download hf://chenbhao/codev@afbc7edaae4e6bb0102ba024b49ce8be89d2264c/src/components/Spinner/useStalledAnimation.ts
-
curl -L -o useStalledAnimation.ts https://huggingface.co/chenbhao/codev/resolve/afbc7edaae4e6bb0102ba024b49ce8be89d2264c/src/components/Spinner/useStalledAnimation.ts
2.5 kB
| import { useRef } from 'react' | |
| // Hook to handle the transition to red when tokens stop flowing. | |
| // Driven by the parent's animation clock time instead of independent intervals, | |
| // so it slows down when the terminal is blurred. | |
| export function useStalledAnimation( | |
| time: number, | |
| currentResponseLength: number, | |
| hasActiveTools = false, | |
| reducedMotion = false, | |
| ): { | |
| isStalled: boolean | |
| stalledIntensity: number | |
| } { | |
| const lastTokenTime = useRef(time) | |
| const lastResponseLength = useRef(currentResponseLength) | |
| const mountTime = useRef(time) | |
| const stalledIntensityRef = useRef(0) | |
| const lastSmoothTime = useRef(time) | |
| // Reset timer when new tokens arrive (check actual length change) | |
| if (currentResponseLength > lastResponseLength.current) { | |
| lastTokenTime.current = time | |
| lastResponseLength.current = currentResponseLength | |
| stalledIntensityRef.current = 0 | |
| lastSmoothTime.current = time | |
| } | |
| // Derive time since last token from animation clock | |
| let timeSinceLastToken: number | |
| if (hasActiveTools) { | |
| timeSinceLastToken = 0 | |
| lastTokenTime.current = time | |
| } else if (currentResponseLength > 0) { | |
| timeSinceLastToken = time - lastTokenTime.current | |
| } else { | |
| timeSinceLastToken = time - mountTime.current | |
| } | |
| // Calculate stalled intensity based on time since last token | |
| // Start showing red after 3 seconds of no new tokens (only when no tools are active) | |
| const isStalled = timeSinceLastToken > 3000 && !hasActiveTools | |
| const intensity = isStalled | |
| ? Math.min((timeSinceLastToken - 3000) / 2000, 1) // Fade over 2 seconds | |
| : 0 | |
| // Smooth intensity transition driven by animation frame ticks | |
| if (!reducedMotion && (intensity > 0 || stalledIntensityRef.current > 0)) { | |
| const dt = time - lastSmoothTime.current | |
| if (dt >= 50) { | |
| const steps = Math.floor(dt / 50) | |
| let current = stalledIntensityRef.current | |
| for (let i = 0; i < steps; i++) { | |
| const diff = intensity - current | |
| if (Math.abs(diff) < 0.01) { | |
| current = intensity | |
| break | |
| } | |
| current += diff * 0.1 | |
| } | |
| stalledIntensityRef.current = current | |
| lastSmoothTime.current = time | |
| } | |
| } else { | |
| stalledIntensityRef.current = intensity | |
| lastSmoothTime.current = time | |
| } | |
| // When reducedMotion is enabled, use instant intensity change | |
| const effectiveIntensity = reducedMotion | |
| ? intensity | |
| : stalledIntensityRef.current | |
| return { isStalled, stalledIntensity: effectiveIntensity } | |
| } | |