forked from ultraworkers/claw-code
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathuseStalledAnimation.ts
More file actions
75 lines (68 loc) · 2.44 KB
/
Copy pathuseStalledAnimation.ts
File metadata and controls
75 lines (68 loc) · 2.44 KB
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
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 }
}