import { Box, Text } from 'ink' import * as React from 'react' import { useEffect, useRef, useState } from 'react' import { getTheme } from '@utils/theme' import { sample } from 'lodash-es' import { getSessionState } from '@utils/sessionState' // NB: The third character in this string is an emoji that // renders on Windows consoles with a green background const CHARACTERS = process.platform === 'darwin' ? ['·', '✢', '✳', '∗', '✻', '✽'] : ['·', '✢', '*', '∗', '✻', '✽'] const MESSAGES = [ 'Accomplishing', 'Actioning', 'Actualizing', 'Baking', 'Brewing', 'Calculating', 'Cerebrating', 'Churning', 'Coding', 'Coalescing', 'Cogitating', 'Computing', 'Conjuring', 'Considering', 'Cooking', 'Crafting', 'Creating', 'Crunching', 'Deliberating', 'Determining', 'Doing', 'Effecting', 'Finagling', 'Forging', 'Forming', 'Generating', 'Hatching', 'Herding', 'Honking', 'Hustling', 'Ideating', 'Inferring', 'Manifesting', 'Marinating', 'Moseying', 'Mulling', 'Mustering', 'Musing', 'Noodling', 'Percolating', 'Pondering', 'Processing', 'Puttering', 'Reticulating', 'Ruminating', 'Schlepping', 'Shucking', 'Simmering', 'Smooshing', 'Spinning', 'Stewing', 'Synthesizing', 'Thinking', 'Transmuting', 'Vibing', 'Working', ] export function Spinner(): React.ReactNode { const frames = [...CHARACTERS, ...[...CHARACTERS].reverse()] const [frame, setFrame] = useState(0) const [elapsedTime, setElapsedTime] = useState(0) const message = useRef(sample(MESSAGES)) const startTime = useRef(Date.now()) useEffect(() => { const timer = setInterval(() => { setFrame(f => (f + 1) % frames.length) }, 120) return () => clearInterval(timer) }, [frames.length]) useEffect(() => { const timer = setInterval(() => { setElapsedTime(Math.floor((Date.now() - startTime.current) / 1000)) }, 1000) return () => clearInterval(timer) }, []) return ( {frames[frame]} {message.current}… ({elapsedTime}s · esc to interrupt) · {getSessionState('currentError')} ) } export function SimpleSpinner(): React.ReactNode { const frames = [...CHARACTERS, ...[...CHARACTERS].reverse()] const [frame, setFrame] = useState(0) useEffect(() => { const timer = setInterval(() => { setFrame(f => (f + 1) % frames.length) }, 120) return () => clearInterval(timer) }, [frames.length]) return ( {frames[frame]} ) }