Files
transcribe/pkg/progress/spinner.go
2026-01-17 19:18:58 -06:00

85 lines
1.5 KiB
Go

package progress
import (
"fmt"
"sync"
"time"
)
// Spinner displays an animated spinner with a message
type Spinner struct {
message string
frames []string
interval time.Duration
stop chan struct{}
done chan struct{}
mu sync.Mutex
running bool
}
// NewSpinner creates a new spinner with the given message
func NewSpinner(message string) *Spinner {
return &Spinner{
message: message,
frames: []string{"⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"},
interval: 80 * time.Millisecond,
stop: make(chan struct{}),
done: make(chan struct{}),
}
}
// Start begins the spinner animation
func (s *Spinner) Start() {
s.mu.Lock()
if s.running {
s.mu.Unlock()
return
}
s.running = true
s.mu.Unlock()
go func() {
i := 0
for {
select {
case <-s.stop:
// Clear the line and signal done
fmt.Print("\r\033[K")
close(s.done)
return
default:
fmt.Printf("\r%s %s", s.frames[i%len(s.frames)], s.message)
i++
time.Sleep(s.interval)
}
}
}()
}
// Stop stops the spinner and clears the line
func (s *Spinner) Stop() {
s.mu.Lock()
if !s.running {
s.mu.Unlock()
return
}
s.running = false
s.mu.Unlock()
close(s.stop)
<-s.done
}
// StopWithMessage stops the spinner and prints a final message
func (s *Spinner) StopWithMessage(message string) {
s.Stop()
fmt.Println(message)
}
// UpdateMessage updates the spinner message while running
func (s *Spinner) UpdateMessage(message string) {
s.mu.Lock()
defer s.mu.Unlock()
s.message = message
}