MCPcopy
hub / github.com/claude-code-best/claude-code / SpinnerWithVerbInner

Function SpinnerWithVerbInner

src/components/Spinner.tsx:101–396  ·  view source on GitHub ↗
({
  mode,
  loadingStartTimeRef,
  totalPausedMsRef,
  pauseStartTimeRef,
  spinnerTip,
  responseLengthRef,
  overrideColor,
  overrideShimmerColor,
  overrideMessage,
  spinnerSuffix,
  verbose,
  hasActiveTools = false,
  leaderIsIdle = false,
}: Props)

Source from the content-addressed store, hash-verified

99}
100
101function SpinnerWithVerbInner({
102 mode,
103 loadingStartTimeRef,
104 totalPausedMsRef,
105 pauseStartTimeRef,
106 spinnerTip,
107 responseLengthRef,
108 overrideColor,
109 overrideShimmerColor,
110 overrideMessage,
111 spinnerSuffix,
112 verbose,
113 hasActiveTools = false,
114 leaderIsIdle = false,
115}: Props): React.ReactNode {
116 const settings = useSettings();
117 const reducedMotion = settings.prefersReducedMotion ?? false;
118
119 // NOTE: useAnimationFrame(50) lives in SpinnerAnimationRow, not here.
120 // This component only re-renders when props or app state change —
121 // it is no longer on the 50ms clock. All `time`-derived values
122 // (frame, glimmer, stalled intensity, token counter, thinking shimmer,
123 // elapsed-time timer) are computed inside the child.
124
125 const tasks = useAppState(s => s.tasks);
126 const viewingAgentTaskId = useAppState(s => s.viewingAgentTaskId);
127 const expandedView = useAppState(s => s.expandedView);
128 const showExpandedTodos = expandedView === 'tasks';
129 const showSpinnerTree = expandedView === 'teammates';
130 const selectedIPAgentIndex = useAppState(s => s.selectedIPAgentIndex);
131 const viewSelectionMode = useAppState(s => s.viewSelectionMode);
132 // Get foregrounded teammate (if viewing a teammate's transcript)
133 const foregroundedTeammate = viewingAgentTaskId ? getViewedTeammateTask({ viewingAgentTaskId, tasks }) : undefined;
134 const { columns } = useTerminalSize();
135 const tasksV2 = useTasksV2();
136
137 // Track thinking status: 'thinking' | number (duration in ms) | null
138 // Shows each state for minimum 2s to avoid UI jank
139 const [thinkingStatus, setThinkingStatus] = useState<'thinking' | number | null>(null);
140 const thinkingStartRef = useRef<number | null>(null);
141
142 useEffect(() => {
143 let showDurationTimer: ReturnType<typeof setTimeout> | null = null;
144 let clearStatusTimer: ReturnType<typeof setTimeout> | null = null;
145
146 if (mode === 'thinking') {
147 // Started thinking
148 if (thinkingStartRef.current === null) {
149 thinkingStartRef.current = Date.now();
150 setThinkingStatus('thinking');
151 }
152 } else if (thinkingStartRef.current !== null) {
153 // Stopped thinking - calculate duration and ensure 2s minimum display
154 const duration = Date.now() - thinkingStartRef.current;
155 const elapsed = Date.now() - thinkingStartRef.current;
156 const remainingThinkingTime = Math.max(0, 2000 - elapsed);
157
158 thinkingStartRef.current = null;

Callers

nothing calls this directly

Calls 15

useSettingsFunction · 0.85
useAppStateFunction · 0.85
getViewedTeammateTaskFunction · 0.85
useTerminalSizeFunction · 0.85
useTasksV2Function · 0.85
showDurationFunction · 0.85
findNextPendingTaskFunction · 0.85
getSpinnerVerbsFunction · 0.85
getEffortSuffixFunction · 0.85
getMainLoopModelFunction · 0.85
isInProcessTeammateTaskFunction · 0.85

Tested by

no test coverage detected