mirror of
				https://github.com/Maks1mS/bubbles.git
				synced 2025-11-03 23:21:22 +03:00 
			
		
		
		
	
		
			
				
	
	
		
			119 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			119 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package spinner
 | 
						|
 | 
						|
import (
 | 
						|
	"time"
 | 
						|
 | 
						|
	tea "github.com/charmbracelet/bubbletea"
 | 
						|
	"github.com/muesli/termenv"
 | 
						|
)
 | 
						|
 | 
						|
// Spinner is a set of frames used in animating the spinner.
 | 
						|
type Spinner = int
 | 
						|
 | 
						|
// Available types of spinners
 | 
						|
const (
 | 
						|
	Line Spinner = iota
 | 
						|
	Dot
 | 
						|
)
 | 
						|
 | 
						|
const (
 | 
						|
	defaultFPS = 9
 | 
						|
)
 | 
						|
 | 
						|
var (
 | 
						|
	// Spinner frames
 | 
						|
	spinners = map[Spinner][]string{
 | 
						|
		Line: {"|", "/", "-", "\\"},
 | 
						|
		Dot:  {"⣾ ", "⣽ ", "⣻ ", "⢿ ", "⡿ ", "⣟ ", "⣯ ", "⣷ "},
 | 
						|
	}
 | 
						|
 | 
						|
	color = termenv.ColorProfile().Color
 | 
						|
)
 | 
						|
 | 
						|
// Model contains the state for the spinner. Use NewModel to create new models
 | 
						|
// rather than using Model as a struct literal.
 | 
						|
type Model struct {
 | 
						|
 | 
						|
	// Type is the set of frames to use. See Spinner.
 | 
						|
	Type Spinner
 | 
						|
 | 
						|
	// FPS is the speed at which the ticker should tick
 | 
						|
	FPS int
 | 
						|
 | 
						|
	// ForegroundColor sets the background color of the spinner. It can be a
 | 
						|
	// hex code or one of the 256 ANSI colors. If the terminal emulator can't
 | 
						|
	// doesn't support the color specified it will automatically degrade
 | 
						|
	// (per github.com/muesli/termenv).
 | 
						|
	ForegroundColor string
 | 
						|
 | 
						|
	// BackgroundColor sets the background color of the spinner. It can be a
 | 
						|
	// hex code or one of the 256 ANSI colors. If the terminal emulator can't
 | 
						|
	// doesn't support the color specified it will automatically degrade
 | 
						|
	// (per github.com/muesli/termenv).
 | 
						|
	BackgroundColor string
 | 
						|
 | 
						|
	// CustomMsgFunc can be used to a custom message on tick. This can be
 | 
						|
	// useful when you have spinners in different parts of your application and
 | 
						|
	// want to differentiate between the messages for clarity and simplicity.
 | 
						|
	// If nil, this setting is ignored.
 | 
						|
	CustomMsgFunc func() tea.Msg
 | 
						|
 | 
						|
	frame int
 | 
						|
}
 | 
						|
 | 
						|
// NewModel returns a model with default values.
 | 
						|
func NewModel() Model {
 | 
						|
	return Model{
 | 
						|
		Type: Line,
 | 
						|
		FPS:  defaultFPS,
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// TickMsg indicates that the timer has ticked and we should render a frame.
 | 
						|
type TickMsg struct{}
 | 
						|
 | 
						|
// Update is the Tea update function. This will advance the spinner one frame
 | 
						|
// every time it's called, regardless the message passed, so be sure the logic
 | 
						|
// is setup so as not to call this Update needlessly.
 | 
						|
func Update(msg tea.Msg, m Model) (Model, tea.Cmd) {
 | 
						|
	m.frame++
 | 
						|
	if m.frame >= len(spinners[m.Type]) {
 | 
						|
		m.frame = 0
 | 
						|
	}
 | 
						|
	if m.CustomMsgFunc != nil {
 | 
						|
		return m, Tick(m)
 | 
						|
	}
 | 
						|
	return m, Tick(m)
 | 
						|
}
 | 
						|
 | 
						|
// View renders the model's view.
 | 
						|
func View(model Model) string {
 | 
						|
	s := spinners[model.Type]
 | 
						|
	if model.frame >= len(s) {
 | 
						|
		return "[error]"
 | 
						|
	}
 | 
						|
 | 
						|
	str := s[model.frame]
 | 
						|
 | 
						|
	if model.ForegroundColor != "" || model.BackgroundColor != "" {
 | 
						|
		return termenv.
 | 
						|
			String(str).
 | 
						|
			Foreground(color(model.ForegroundColor)).
 | 
						|
			Background(color(model.BackgroundColor)).
 | 
						|
			String()
 | 
						|
	}
 | 
						|
 | 
						|
	return str
 | 
						|
}
 | 
						|
 | 
						|
// Tick is the command used to advance the spinner one frame.
 | 
						|
func Tick(model Model) tea.Cmd {
 | 
						|
	return func() tea.Msg {
 | 
						|
		time.Sleep(time.Second / time.Duration(model.FPS))
 | 
						|
		if model.CustomMsgFunc != nil {
 | 
						|
			return model.CustomMsgFunc()
 | 
						|
		}
 | 
						|
		return TickMsg{}
 | 
						|
	}
 | 
						|
}
 |