Move worker into account tab
This commit is contained in:
parent
ffba561334
commit
4074445cbb
8 changed files with 86 additions and 38 deletions
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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))
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
||||||
for _, ch := range str {
|
newline := func() {
|
||||||
tb.SetCell(geo.Col, geo.Row, ch, ref.Fg, ref.Bg)
|
|
||||||
geo.Col++
|
|
||||||
if geo.Col == _geo.Col+geo.Width {
|
|
||||||
// TODO: Abort when out of room?
|
// TODO: Abort when out of room?
|
||||||
geo.Col = _geo.Col
|
geo.Col = _geo.Col
|
||||||
geo.Row++
|
geo.Row++
|
||||||
}
|
}
|
||||||
|
for _, ch := range str {
|
||||||
|
switch ch {
|
||||||
|
case '\n':
|
||||||
|
newline()
|
||||||
|
case '\r':
|
||||||
|
geo.Col = _geo.Col
|
||||||
|
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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
15
ui/types.go
15
ui/types.go
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
13
ui/ui.go
13
ui/ui.go
|
@ -12,6 +12,7 @@ func Initialize(conf *config.AercConfig) (*UIState, error) {
|
||||||
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
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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()
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue