Move worker into account tab

This commit is contained in:
Drew DeVault 2018-01-11 09:04:18 -05:00
parent ffba561334
commit 4074445cbb
8 changed files with 86 additions and 38 deletions

View File

@ -5,8 +5,6 @@ import (
"git.sr.ht/~sircmpwn/aerc2/config" "git.sr.ht/~sircmpwn/aerc2/config"
"git.sr.ht/~sircmpwn/aerc2/ui" "git.sr.ht/~sircmpwn/aerc2/ui"
"git.sr.ht/~sircmpwn/aerc2/worker"
"git.sr.ht/~sircmpwn/aerc2/worker/types"
) )
func main() { func main() {
@ -19,27 +17,15 @@ func main() {
panic(err) panic(err)
} }
defer _ui.Close() defer _ui.Close()
var workers []worker.Worker
for _, account := range conf.Accounts { for _, account := range conf.Accounts {
work, err := worker.NewWorker(account.Source) tab, err := ui.NewAccountTab(&account)
if err != nil { if err != nil {
panic(err) panic(err)
} }
go work.Run() _ui.AddTab(tab)
work.PostAction(types.Configure{Config: account})
workers = append(workers, work)
// TODO: Give tabs ownership over their workers
_ui.AddTab(ui.NewAccountTab(&account, &work))
} }
for !_ui.Exit { for !_ui.Exit {
activity := false if !_ui.Tick() {
for _, worker := range workers {
if msg := worker.GetMessage(); msg != nil {
activity = true
}
}
activity = _ui.Tick() || activity
if !activity {
time.Sleep(100 * time.Millisecond) time.Sleep(100 * time.Millisecond)
} }
} }

View File

@ -1,25 +1,35 @@
package ui package ui
import ( import (
"fmt"
tb "github.com/nsf/termbox-go" tb "github.com/nsf/termbox-go"
"git.sr.ht/~sircmpwn/aerc2/config" "git.sr.ht/~sircmpwn/aerc2/config"
"git.sr.ht/~sircmpwn/aerc2/worker" "git.sr.ht/~sircmpwn/aerc2/worker"
"git.sr.ht/~sircmpwn/aerc2/worker/types"
) )
type AccountTab struct { type AccountTab struct {
Config *config.AccountConfig Config *config.AccountConfig
Worker *worker.Worker Worker worker.Worker
Parent *UIState Parent *UIState
counter int counter int
log []string
} }
func NewAccountTab(conf *config.AccountConfig, work *worker.Worker) *AccountTab { func NewAccountTab(conf *config.AccountConfig) (*AccountTab, error) {
work, err := worker.NewWorker(conf.Source)
if err != nil {
return nil, err
}
go work.Run()
work.PostAction(types.Configure{Config: conf})
return &AccountTab{ return &AccountTab{
Config: conf, Config: conf,
Worker: work, Worker: work,
} }, nil
} }
func (acc *AccountTab) Name() string { func (acc *AccountTab) Name() string {
@ -32,13 +42,26 @@ func (acc *AccountTab) SetParent(parent *UIState) {
func (acc *AccountTab) Render(at Geometry) { func (acc *AccountTab) Render(at Geometry) {
cell := tb.Cell{ cell := tb.Cell{
Ch: ' ',
Fg: tb.ColorDefault, Fg: tb.ColorDefault,
Bg: tb.ColorDefault, Bg: tb.ColorDefault,
} }
TPrintf(&at, cell, "%s %d", acc.Name(), acc.counter) TFill(at, cell)
TPrintf(&at, cell, "%s %d\n", acc.Name(), acc.counter)
for _, str := range acc.log {
TPrintf(&at, cell, "%s\n", str)
}
acc.counter++ acc.counter++
if acc.counter%10000 == 0 { if acc.counter%10000 == 0 {
acc.counter = 0 acc.counter = 0
} }
acc.Parent.InvalidateFrom(acc) acc.Parent.InvalidateFrom(acc)
} }
func (acc *AccountTab) GetChannel() chan types.WorkerMessage {
return acc.Worker.GetMessages()
}
func (acc *AccountTab) HandleMessage(msg types.WorkerMessage) {
acc.log = append(acc.log, fmt.Sprintf("<- %T", msg))
}

View File

@ -9,13 +9,33 @@ import (
func TPrintf(geo *Geometry, ref tb.Cell, format string, a ...interface{}) { func TPrintf(geo *Geometry, ref tb.Cell, format string, a ...interface{}) {
str := fmt.Sprintf(format, a...) str := fmt.Sprintf(format, a...)
_geo := *geo _geo := *geo
newline := func() {
// TODO: Abort when out of room?
geo.Col = _geo.Col
geo.Row++
}
for _, ch := range str { for _, ch := range str {
tb.SetCell(geo.Col, geo.Row, ch, ref.Fg, ref.Bg) switch ch {
geo.Col++ case '\n':
if geo.Col == _geo.Col+geo.Width { newline()
// TODO: Abort when out of room? case '\r':
geo.Col = _geo.Col geo.Col = _geo.Col
geo.Row++ default:
tb.SetCell(geo.Col, geo.Row, ch, ref.Fg, ref.Bg)
geo.Col++
if geo.Col == _geo.Col+geo.Width {
newline()
}
} }
} }
} }
func TFill(geo Geometry, ref tb.Cell) {
_geo := geo
for ; geo.Row < geo.Height; geo.Row++ {
for ; geo.Col < geo.Width; geo.Col++ {
tb.SetCell(geo.Col, geo.Row, ref.Ch, ref.Fg, ref.Bg)
}
geo.Col = _geo.Col
}
}

View File

@ -4,20 +4,19 @@ import (
tb "github.com/nsf/termbox-go" tb "github.com/nsf/termbox-go"
"git.sr.ht/~sircmpwn/aerc2/config" "git.sr.ht/~sircmpwn/aerc2/config"
"git.sr.ht/~sircmpwn/aerc2/worker/types"
) )
const ( const (
Valid = 0 Valid = 0
InvalidateTabList = 1 << iota InvalidateTabList = 1 << iota
InvalidateTabView InvalidateTabView
InvalidateSidebar
InvalidateStatusBar InvalidateStatusBar
) )
const ( const (
InvalidateAll = InvalidateTabList | InvalidateAll = InvalidateTabList |
InvalidateTabView | InvalidateTabView |
InvalidateSidebar |
InvalidateStatusBar InvalidateStatusBar
) )
@ -34,6 +33,16 @@ type AercTab interface {
SetParent(parent *UIState) SetParent(parent *UIState)
} }
type WorkerListener interface {
GetChannel() chan types.WorkerMessage
HandleMessage(msg types.WorkerMessage)
}
type wrappedMessage struct {
msg types.WorkerMessage
listener WorkerListener
}
type UIState struct { type UIState struct {
Config *config.AercConfig Config *config.AercConfig
Exit bool Exit bool
@ -57,4 +66,6 @@ type UIState struct {
} }
tbEvents chan tb.Event tbEvents chan tb.Event
// Aggregate channel for all worker messages
workerEvents chan wrappedMessage
} }

View File

@ -11,7 +11,8 @@ func Initialize(conf *config.AercConfig) (*UIState, error) {
Config: conf, Config: conf,
InvalidPanes: InvalidateAll, InvalidPanes: InvalidateAll,
tbEvents: make(chan tb.Event, 10), tbEvents: make(chan tb.Event, 10),
workerEvents: make(chan wrappedMessage),
} }
if err := tb.Init(); err != nil { if err := tb.Init(); err != nil {
return nil, err return nil, err
@ -33,6 +34,16 @@ func (state *UIState) Close() {
func (state *UIState) AddTab(tab AercTab) { func (state *UIState) AddTab(tab AercTab) {
tab.SetParent(state) tab.SetParent(state)
state.Tabs = append(state.Tabs, tab) state.Tabs = append(state.Tabs, tab)
if listener, ok := tab.(WorkerListener); ok {
go (func() {
for msg := range listener.GetChannel() {
state.workerEvents <- wrappedMessage{
msg: msg,
listener: listener,
}
}
})()
}
} }
func (state *UIState) Invalidate(what uint) { func (state *UIState) Invalidate(what uint) {
@ -67,6 +78,8 @@ func (state *UIState) Tick() bool {
case tb.EventResize: case tb.EventResize:
state.Invalidate(InvalidateAll) state.Invalidate(InvalidateAll)
} }
case msg := <-state.workerEvents:
msg.listener.HandleMessage(msg.msg)
default: default:
// no-op // no-op
break break

View File

@ -18,13 +18,8 @@ func NewIMAPWorker() *IMAPWorker {
} }
} }
func (w *IMAPWorker) GetMessage() types.WorkerMessage { func (w *IMAPWorker) GetMessages() chan types.WorkerMessage {
select { return w.messages
case msg := <-w.messages:
return msg
default:
return nil
}
} }
func (w *IMAPWorker) PostAction(msg types.WorkerMessage) { func (w *IMAPWorker) PostAction(msg types.WorkerMessage) {

View File

@ -33,7 +33,7 @@ type Ping struct {
type Configure struct { type Configure struct {
Message Message
Config config.AccountConfig Config *config.AccountConfig
} }
type Connect struct { type Connect struct {

View File

@ -9,7 +9,7 @@ import (
) )
type Worker interface { type Worker interface {
GetMessage() types.WorkerMessage GetMessages() chan types.WorkerMessage
PostAction(types.WorkerMessage) PostAction(types.WorkerMessage)
Run() Run()
} }