Lay out message list widget basic design

This commit is contained in:
Drew DeVault 2019-03-14 21:37:00 -04:00
parent b3896476a0
commit 0f8b7a1203
3 changed files with 108 additions and 4 deletions

View File

@ -21,6 +21,7 @@ type AccountView struct {
interactive ui.Interactive interactive ui.Interactive
onInvalidate func(d ui.Drawable) onInvalidate func(d ui.Drawable)
runCmd func(cmd string) error runCmd func(cmd string) error
msglist *MessageList
msgStores map[string]*MessageStore msgStores map[string]*MessageStore
statusline *StatusLine statusline *StatusLine
statusbar *ui.Stack statusbar *ui.Stack
@ -41,9 +42,6 @@ func NewAccountView(conf *config.AccountConfig,
{ui.SIZE_EXACT, 20}, {ui.SIZE_EXACT, 20},
{ui.SIZE_WEIGHT, 1}, {ui.SIZE_WEIGHT, 1},
}) })
spinner := NewSpinner()
spinner.Start()
grid.AddChild(spinner).At(0, 1)
grid.AddChild(statusbar).At(1, 1) grid.AddChild(statusbar).At(1, 1)
worker, err := worker.NewWorker(conf.Source, logger) worker, err := worker.NewWorker(conf.Source, logger)
@ -60,11 +58,15 @@ func NewAccountView(conf *config.AccountConfig,
dirlist := NewDirectoryList(conf, logger, worker) dirlist := NewDirectoryList(conf, logger, worker)
grid.AddChild(ui.NewBordered(dirlist, ui.BORDER_RIGHT)).Span(2, 1) grid.AddChild(ui.NewBordered(dirlist, ui.BORDER_RIGHT)).Span(2, 1)
msglist := NewMessageList(logger, worker)
grid.AddChild(msglist).At(0, 1)
acct := &AccountView{ acct := &AccountView{
conf: conf, conf: conf,
dirlist: dirlist, dirlist: dirlist,
grid: grid, grid: grid,
logger: logger, logger: logger,
msglist: msglist,
msgStores: make(map[string]*MessageStore), msgStores: make(map[string]*MessageStore),
runCmd: runCmd, runCmd: runCmd,
statusbar: statusbar, statusbar: statusbar,
@ -173,7 +175,8 @@ func (acct *AccountView) onMessage(msg types.WorkerMessage) {
case *types.OpenDirectory: case *types.OpenDirectory:
acct.worker.PostAction(&types.FetchDirectoryContents{}, acct.worker.PostAction(&types.FetchDirectoryContents{},
func(msg types.WorkerMessage) { func(msg types.WorkerMessage) {
// TODO: Do we care store := acct.msgStores[acct.dirlist.selected]
acct.msglist.SetStore(store)
}) })
} }
case *types.DirectoryInfo: case *types.DirectoryInfo:

View File

@ -1,6 +1,12 @@
package widgets package widgets
import ( import (
"log"
"github.com/gdamore/tcell"
"git.sr.ht/~sircmpwn/aerc2/config"
"git.sr.ht/~sircmpwn/aerc2/lib/ui"
"git.sr.ht/~sircmpwn/aerc2/worker/types" "git.sr.ht/~sircmpwn/aerc2/worker/types"
) )
@ -34,3 +40,86 @@ func (store *MessageStore) Update(msg types.WorkerMessage) {
break break
} }
} }
type MessageList struct {
conf *config.AercConfig
logger *log.Logger
onInvalidate func(d ui.Drawable)
spinner *Spinner
store *MessageStore
worker *types.Worker
}
// TODO: fish in config
func NewMessageList(logger *log.Logger, worker *types.Worker) *MessageList {
ml := &MessageList{
logger: logger,
spinner: NewSpinner(),
worker: worker,
}
ml.spinner.OnInvalidate(func(_ ui.Drawable) {
ml.Invalidate()
})
// TODO: stop spinner, probably
ml.spinner.Start()
return ml
}
func (ml *MessageList) OnInvalidate(onInvalidate func(d ui.Drawable)) {
ml.onInvalidate = onInvalidate
}
func (ml *MessageList) Invalidate() {
if ml.onInvalidate != nil {
ml.onInvalidate(ml)
}
}
func (ml *MessageList) Draw(ctx *ui.Context) {
ctx.Fill(0, 0, ctx.Width(), ctx.Height(), ' ', tcell.StyleDefault)
if ml.store == nil {
ml.spinner.Draw(ctx)
return
}
var (
needsHeaders []uint64
row int = 0
)
for uid, msg := range ml.store.Messages {
if row >= ctx.Height() {
break
}
if msg == nil {
needsHeaders = append(needsHeaders, uid)
ml.spinner.Draw(ctx.Subcontext(0, row, ctx.Width(), 1))
}
row += 1
}
if len(needsHeaders) != 0 {
ml.spinner.Start()
} else {
ml.spinner.Stop()
}
// TODO: Fetch these messages
}
func (ml *MessageList) SetStore(store *MessageStore) {
if ml.store == store {
return
}
ml.store = store
if store != nil {
ml.spinner.Stop()
} else {
ml.spinner.Start()
}
ml.Invalidate()
}

View File

@ -36,6 +36,10 @@ func NewSpinner() *Spinner {
} }
func (s *Spinner) Start() { func (s *Spinner) Start() {
if s.IsRunning() {
return
}
s.frame = 0 s.frame = 0
go func() { go func() {
for { for {
@ -54,6 +58,10 @@ func (s *Spinner) Start() {
} }
func (s *Spinner) Stop() { func (s *Spinner) Stop() {
if !s.IsRunning() {
return
}
s.stop <- nil s.stop <- nil
s.frame = -1 s.frame = -1
s.Invalidate() s.Invalidate()
@ -64,6 +72,10 @@ func (s *Spinner) IsRunning() bool {
} }
func (s *Spinner) Draw(ctx *ui.Context) { func (s *Spinner) Draw(ctx *ui.Context) {
if !s.IsRunning() {
return
}
ctx.Fill(0, 0, ctx.Width(), ctx.Height(), ' ', tcell.StyleDefault) ctx.Fill(0, 0, ctx.Width(), ctx.Height(), ' ', tcell.StyleDefault)
col := ctx.Width()/2 - len(frames[0])/2 + 1 col := ctx.Width()/2 - len(frames[0])/2 + 1
ctx.Printf(col, 0, tcell.StyleDefault, "%s", frames[s.frame]) ctx.Printf(col, 0, tcell.StyleDefault, "%s", frames[s.frame])