From 3872a58b8fd0d89e65339a8f37d1af669dc945ee Mon Sep 17 00:00:00 2001 From: Christian Rocha Date: Thu, 29 Jan 2026 11:11:28 -0500 Subject: [PATCH] wip(spinner): basic anim loop --- internal/ui/spinner/example/main.go | 7 +++ internal/ui/spinner/spinner.go | 66 ++++++++++++++++++----------- 2 files changed, 49 insertions(+), 24 deletions(-) diff --git a/internal/ui/spinner/example/main.go b/internal/ui/spinner/example/main.go index 66f6ac1c218de0ffe11c88090801a737f8088897..5fd9dce6e7f3ea6297ae025315ac27460e839a54 100644 --- a/internal/ui/spinner/example/main.go +++ b/internal/ui/spinner/example/main.go @@ -45,6 +45,13 @@ func (m Model) View() tea.View { } func main() { + f, err := tea.LogToFile("spinner.log", "spinner") + if err != nil { + fmt.Fprintf(os.Stderr, "Error creating log file: %v\n", err) + os.Exit(1) + } + defer f.Close() + if _, err := tea.NewProgram(Model{ spinner: spinner.NewSpinner(), }).Run(); err != nil { diff --git a/internal/ui/spinner/spinner.go b/internal/ui/spinner/spinner.go index 6c67745753db78aec345583ed2110464bb5b55fc..281673c68d7ebd2424ccc97d3b66a34b239bbbb3 100644 --- a/internal/ui/spinner/spinner.go +++ b/internal/ui/spinner/spinner.go @@ -2,6 +2,7 @@ package spinner import ( + "log" "strings" "sync/atomic" "time" @@ -10,11 +11,13 @@ import ( ) const ( - fps = 24 - emptyChar = '░' + fps = 24 + pauseSteps = 72 + width = 12 ) var blocks = []rune{ + ' ', '▁', '▂', '▃', @@ -33,26 +36,23 @@ func nextID() int { return int(atomic.AddInt64(&lastID, 1)) } -type StepMsg struct{ ID int } - -type Config struct { - Width int -} - -func DefaultConfig() Config { - return Config{Width: 12} +type StepMsg struct { + ID int + tag int } type Spinner struct { - Config Config - id int - index int + id int + tag int + index int + pause int + cells []int } func NewSpinner() Spinner { return Spinner{ - id: nextID(), - Config: DefaultConfig(), + id: nextID(), + cells: make([]int, width), } } @@ -66,10 +66,28 @@ func (s Spinner) Update(msg tea.Msg) (Spinner, tea.Cmd) { // Reject events from other spinners. return s, nil } - s.index++ - if s.index > s.Config.Width-1 { - s.index = 0 + + if s.pause > 0 { + s.pause-- + log.Println("pausing", s.pause) + } else { + s.index++ + if s.index > width { + s.pause = pauseSteps + s.index = 0 + } + } + + for i, c := range s.cells { + if s.index == i { + s.cells[i] = len(blocks) - 1 + } else { + s.cells[i] = max(0, c-1) + } + } + + s.tag++ return s, s.Step() } return s, nil @@ -82,13 +100,13 @@ func (s Spinner) Step() tea.Cmd { } func (s Spinner) View() string { + if len(blocks) == 0 { + return "" + } + var b strings.Builder - for i := range s.Config.Width { - if i == s.index { - b.WriteRune(blocks[len(blocks)-1]) - continue - } - b.WriteRune(emptyChar) + for i := range s.cells { + b.WriteRune(blocks[s.cells[i]]) } return b.String()