Prevent spinner from responding to extra, unintentional tick messages

This commit is contained in:
Christian Rocha 2020-12-11 12:00:07 -05:00 committed by Christian Rocha
parent 37a85afcd1
commit 3be2d0585b

View File

@ -99,6 +99,7 @@ type Model struct {
frame int frame int
startTime time.Time startTime time.Time
tag int
} }
// Start resets resets the spinner start time. For use with MinimumLifetime and // Start resets resets the spinner start time. For use with MinimumLifetime and
@ -121,7 +122,8 @@ func (m Model) hidden() bool {
return m.startTime.Add(m.HideFor).After(time.Now()) return m.startTime.Add(m.HideFor).After(time.Now())
} }
// finished returns whether Model.MinimumLifetimeReached has been met. // finished returns whether the minimum lifetime of this spinner has been
// exceeded.
func (m Model) finished() bool { func (m Model) finished() bool {
if m.startTime.IsZero() { if m.startTime.IsZero() {
return true return true
@ -156,19 +158,30 @@ func NewModel() Model {
// TickMsg indicates that the timer has ticked and we should render a frame. // TickMsg indicates that the timer has ticked and we should render a frame.
type TickMsg struct { type TickMsg struct {
Time time.Time Time time.Time
tag int
} }
// Update is the Tea update function. This will advance the spinner one frame // 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 // every time it's called, regardless the message passed, so be sure the logic
// is setup so as not to call this Update needlessly. // is setup so as not to call this Update needlessly.
func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) { func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) {
switch msg.(type) { switch msg := msg.(type) {
case TickMsg: case TickMsg:
// If a tag is set, and it's not the one we expect, reject the message.
// This prevents the spinner from receiving too many messages and
// this spinning too fast.
if msg.tag > 0 && msg.tag != m.tag {
return m, nil
}
m.frame++ m.frame++
if m.frame >= len(m.Spinner.Frames) { if m.frame >= len(m.Spinner.Frames) {
m.frame = 0 m.frame = 0
} }
return m, m.tick()
m.tag++
return m, m.tick(m.tag)
default: default:
return m, nil return m, nil
} }
@ -193,15 +206,17 @@ func (m Model) View() string {
return frame return frame
} }
// Tick is the command used to advance the spinner one frame. // Tick is the command used to advance the spinner one frame. Use this command
// to effectively start the spinner.
func Tick() tea.Msg { func Tick() tea.Msg {
return TickMsg{Time: time.Now()} return TickMsg{Time: time.Now()}
} }
func (m Model) tick() tea.Cmd { func (m Model) tick(tag int) tea.Cmd {
return tea.Tick(m.Spinner.FPS, func(t time.Time) tea.Msg { return tea.Tick(m.Spinner.FPS, func(t time.Time) tea.Msg {
return TickMsg{ return TickMsg{
Time: t, Time: t,
tag: tag,
} }
}) })
} }