Add loading spinner

This commit is contained in:
Drew DeVault 2019-01-13 20:02:21 -05:00
parent f87fe502a6
commit a782b709d1
3 changed files with 190 additions and 1 deletions

View file

@ -17,13 +17,24 @@ type DirectoryList struct {
logger *log.Logger logger *log.Logger
onInvalidate func(d ui.Drawable) onInvalidate func(d ui.Drawable)
selected string selected string
spinner *Spinner
worker *types.Worker worker *types.Worker
} }
func NewDirectoryList(conf *config.AccountConfig, func NewDirectoryList(conf *config.AccountConfig,
logger *log.Logger, worker *types.Worker) *DirectoryList { 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)) { func (dirlist *DirectoryList) UpdateList(done func(dirs []string)) {
@ -37,6 +48,7 @@ func (dirlist *DirectoryList) UpdateList(done func(dirs []string)) {
case *types.Done: case *types.Done:
sort.Strings(dirs) sort.Strings(dirs)
dirlist.dirs = dirs dirlist.dirs = dirs
dirlist.spinner.Stop()
dirlist.Invalidate() dirlist.Invalidate()
if done != nil { if done != nil {
done(dirs) done(dirs)
@ -63,6 +75,12 @@ func (dirlist *DirectoryList) Invalidate() {
func (dirlist *DirectoryList) Draw(ctx *ui.Context) { func (dirlist *DirectoryList) Draw(ctx *ui.Context) {
ctx.Fill(0, 0, ctx.Width(), ctx.Height(), ' ', tcell.StyleDefault) ctx.Fill(0, 0, ctx.Width(), ctx.Height(), ' ', tcell.StyleDefault)
if dirlist.spinner.IsRunning() {
dirlist.spinner.Draw(ctx)
return
}
row := 0 row := 0
for _, name := range dirlist.dirs { for _, name := range dirlist.dirs {
if row >= ctx.Height() { if row >= ctx.Height() {

80
widgets/spinner.go Normal file
View file

@ -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)
}
}

91
worker/messages.go Normal file
View file

@ -0,0 +1,91 @@
package worker
import (
"crypto/x509"
"git.sr.ht/~sircmpwn/aerc2/config"
)
type WorkerMessage interface {
InResponseTo() WorkerMessage
}
type Message struct {
inResponseTo WorkerMessage
}
func RespondTo(msg WorkerMessage) Message {
return Message{
inResponseTo: msg,
}
}
func (m Message) InResponseTo() WorkerMessage {
return m.inResponseTo
}
// Meta-messages
type Done struct {
Message
}
type Error struct {
Message
Error error
}
type Unsupported struct {
Message
}
// Actions
type ApproveCertificate struct {
Message
Approved bool
}
type Configure struct {
Message
Config *config.AccountConfig
}
type Connect struct {
Message
}
type Disconnect struct {
Message
}
type ListDirectories struct {
Message
}
type OpenDirectory struct {
Message
Directory string
}
// Messages
type CertificateApprovalRequest struct {
Message
CertPool *x509.CertPool
}
type Directory struct {
Message
Attributes []string
Name string
}
type DirectoryInfo struct {
Message
Flags []string
Name string
ReadOnly bool
Exists, Recent, Unseen int
}