diff options
author | Drew DeVault <sir@cmpwn.com> | 2019-01-13 20:02:21 -0500 |
---|---|---|
committer | Drew DeVault <sir@cmpwn.com> | 2019-01-13 20:02:21 -0500 |
commit | a782b709d1312bfe80dda7c864de96ba1c854bc2 (patch) | |
tree | 206846b95e787e302694cbc3f812e173eeb76b5e /widgets | |
parent | f87fe502a6d252bac9da5f08fd2aa682a9fc2277 (diff) |
Add loading spinner
Diffstat (limited to 'widgets')
-rw-r--r-- | widgets/directories.go | 20 | ||||
-rw-r--r-- | widgets/spinner.go | 80 |
2 files changed, 99 insertions, 1 deletions
diff --git a/widgets/directories.go b/widgets/directories.go index 13018bb..11fe2d6 100644 --- a/widgets/directories.go +++ b/widgets/directories.go @@ -17,13 +17,24 @@ type DirectoryList struct { logger *log.Logger onInvalidate func(d ui.Drawable) selected string + spinner *Spinner worker *types.Worker } func NewDirectoryList(conf *config.AccountConfig, logger *log.Logger, worker *types.Worker) *DirectoryList { - return &DirectoryList{conf: conf, logger: logger, worker: worker} + dirlist := &DirectoryList{ + conf: conf, + logger: logger, + spinner: NewSpinner(), + worker: worker, + } + dirlist.spinner.OnInvalidate(func(_ ui.Drawable) { + dirlist.Invalidate() + }) + dirlist.spinner.Start() + return dirlist } func (dirlist *DirectoryList) UpdateList(done func(dirs []string)) { @@ -37,6 +48,7 @@ func (dirlist *DirectoryList) UpdateList(done func(dirs []string)) { case *types.Done: sort.Strings(dirs) dirlist.dirs = dirs + dirlist.spinner.Stop() dirlist.Invalidate() if done != nil { done(dirs) @@ -63,6 +75,12 @@ func (dirlist *DirectoryList) Invalidate() { func (dirlist *DirectoryList) Draw(ctx *ui.Context) { ctx.Fill(0, 0, ctx.Width(), ctx.Height(), ' ', tcell.StyleDefault) + + if dirlist.spinner.IsRunning() { + dirlist.spinner.Draw(ctx) + return + } + row := 0 for _, name := range dirlist.dirs { if row >= ctx.Height() { diff --git a/widgets/spinner.go b/widgets/spinner.go new file mode 100644 index 0000000..2e7e367 --- /dev/null +++ b/widgets/spinner.go @@ -0,0 +1,80 @@ +package widgets + +import ( + "time" + + "github.com/gdamore/tcell" + + "git.sr.ht/~sircmpwn/aerc2/lib/ui" +) + +var ( + frames = []string{ + "[..] ", + " [..] ", + " [..] ", + " [..] ", + " [..]", + " [..] ", + " [..] ", + " [..] ", + } +) + +type Spinner struct { + frame int + onInvalidate func(d ui.Drawable) + stop chan interface{} +} + +func NewSpinner() *Spinner { + spinner := Spinner{ + stop: make(chan interface{}), + frame: -1, + } + return &spinner +} + +func (s *Spinner) Start() { + s.frame = 0 + go func() { + for { + select { + case <-s.stop: + return + case <-time.After(200 * time.Millisecond): + s.frame++ + if s.frame >= len(frames) { + s.frame = 0 + } + s.Invalidate() + } + } + }() +} + +func (s *Spinner) Stop() { + s.stop <- nil + s.frame = -1 + s.Invalidate() +} + +func (s *Spinner) IsRunning() bool { + return s.frame != -1 +} + +func (s *Spinner) Draw(ctx *ui.Context) { + ctx.Fill(0, 0, ctx.Width(), ctx.Height(), ' ', tcell.StyleDefault) + col := ctx.Width()/2 - len(frames[0])/2 + 1 + ctx.Printf(col, 0, tcell.StyleDefault, "%s", frames[s.frame]) +} + +func (s *Spinner) OnInvalidate(onInvalidate func(d ui.Drawable)) { + s.onInvalidate = onInvalidate +} + +func (s *Spinner) Invalidate() { + if s.onInvalidate != nil { + s.onInvalidate(s) + } +} |