♻️ I think I'm finally happy with the Spinner implementation
This commit is contained in:
parent
01e3c3aade
commit
2552adbd3e
1 changed files with 43 additions and 24 deletions
|
|
@ -58,28 +58,47 @@ func (m model) View() string {
|
||||||
return str
|
return str
|
||||||
}
|
}
|
||||||
|
|
||||||
func Spin(ctx context.Context, message string) (chan string, chan error) {
|
type Spinner interface {
|
||||||
|
Wait() error
|
||||||
|
SetMessage(string)
|
||||||
|
Err() error
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ Spinner = new(spin)
|
||||||
|
|
||||||
|
type spin struct {
|
||||||
|
p *tea.Program
|
||||||
|
err error
|
||||||
|
finished chan struct{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *spin) Wait() error {
|
||||||
|
<-s.finished
|
||||||
|
return s.Err()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *spin) SetMessage(msg string) {
|
||||||
|
s.p.Send(textMessage(msg))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *spin) Err() error {
|
||||||
|
if errors.Is(s.err, context.Canceled) {
|
||||||
|
return nil
|
||||||
|
} else if errors.Is(s.err, context.DeadlineExceeded) {
|
||||||
|
return nil
|
||||||
|
} else if errors.Is(s.err, tea.ErrProgramKilled) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return s.err
|
||||||
|
}
|
||||||
|
|
||||||
|
func Spin(ctx context.Context, message string) Spinner {
|
||||||
p := tea.NewProgram(newModel(message), tea.WithContext(ctx))
|
p := tea.NewProgram(newModel(message), tea.WithContext(ctx))
|
||||||
|
s := &spin{p: p, finished: make(chan struct{}, 1)}
|
||||||
msgChan := make(chan string, 10)
|
|
||||||
errChan := make(chan error)
|
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
for {
|
_, err := s.p.Run()
|
||||||
m := <-msgChan
|
s.err = err
|
||||||
p.Send(textMessage(m))
|
s.finished <- struct{}{}
|
||||||
}
|
|
||||||
}()
|
}()
|
||||||
go func() {
|
return s
|
||||||
_, err := p.Run()
|
|
||||||
if errors.Is(err, context.Canceled) {
|
|
||||||
err = nil
|
|
||||||
} else if errors.Is(err, context.DeadlineExceeded) {
|
|
||||||
err = nil
|
|
||||||
} else if errors.Is(err, tea.ErrProgramKilled) {
|
|
||||||
err = nil
|
|
||||||
}
|
|
||||||
errChan <- err
|
|
||||||
}()
|
|
||||||
return msgChan, errChan
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue