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]}
)
}