aboutsummaryrefslogtreecommitdiffstats
path: root/widgets/msglist.go
diff options
context:
space:
mode:
authorDrew DeVault <sir@cmpwn.com>2019-03-14 21:51:29 -0400
committerDrew DeVault <sir@cmpwn.com>2019-03-14 21:51:29 -0400
commit11f0a7267fd1a9d1c6dd55e1dc044b8ed639bbc0 (patch)
tree80e2456edadfdcd7c6a8e02ab4830c1139816174 /widgets/msglist.go
parent0f8b7a1203309ebec0dc78baf3f195671eadac2d (diff)
downloadaerc-11f0a7267fd1a9d1c6dd55e1dc044b8ed639bbc0.tar.gz
Implement message store side of message fetching
Diffstat (limited to 'widgets/msglist.go')
-rw-r--r--widgets/msglist.go62
1 files changed, 52 insertions, 10 deletions
diff --git a/widgets/msglist.go b/widgets/msglist.go
index 8e3c2eb3..fef396bc 100644
--- a/widgets/msglist.go
+++ b/widgets/msglist.go
@@ -3,6 +3,7 @@ package widgets
import (
"log"
+ "github.com/emersion/go-imap"
"github.com/gdamore/tcell"
"git.sr.ht/~sircmpwn/aerc2/config"
@@ -12,20 +13,52 @@ import (
type MessageStore struct {
DirInfo types.DirectoryInfo
- Messages map[uint64]*types.MessageInfo
+ Messages map[uint32]*types.MessageInfo
+ // Map of uids we've asked the worker to fetch
+ onUpdate func(store *MessageStore)
+ pendingBodies map[uint32]interface{}
+ pendingHeaders map[uint32]interface{}
+ worker *types.Worker
}
-func NewMessageStore(dirInfo *types.DirectoryInfo) *MessageStore {
- return &MessageStore{DirInfo: *dirInfo}
+func NewMessageStore(worker *types.Worker,
+ dirInfo *types.DirectoryInfo) *MessageStore {
+
+ return &MessageStore{
+ DirInfo: *dirInfo,
+
+ pendingBodies: make(map[uint32]interface{}),
+ pendingHeaders: make(map[uint32]interface{}),
+ worker: worker,
+ }
+}
+
+func (store *MessageStore) FetchHeaders(uids []uint32) {
+ // TODO: this could be optimized by pre-allocating toFetch and trimming it
+ // at the end. In practice we expect to get most messages back in one frame.
+ var toFetch imap.SeqSet
+ for _, uid := range uids {
+ if _, ok := store.pendingHeaders[uid]; !ok {
+ toFetch.AddNum(uint32(uid))
+ store.pendingHeaders[uid] = nil
+ }
+ }
+ if !toFetch.Empty() {
+ store.worker.PostAction(&types.FetchMessageHeaders{
+ Uids: toFetch,
+ }, nil)
+ }
}
func (store *MessageStore) Update(msg types.WorkerMessage) {
+ update := false
switch msg := msg.(type) {
case *types.DirectoryInfo:
store.DirInfo = *msg
+ update = true
break
case *types.DirectoryContents:
- newMap := make(map[uint64]*types.MessageInfo)
+ newMap := make(map[uint32]*types.MessageInfo)
for _, uid := range msg.Uids {
if msg, ok := store.Messages[uid]; ok {
newMap[uid] = msg
@@ -34,11 +67,23 @@ func (store *MessageStore) Update(msg types.WorkerMessage) {
}
}
store.Messages = newMap
+ update = true
break
case *types.MessageInfo:
store.Messages[msg.Uid] = msg
+ if _, ok := store.pendingHeaders[msg.Uid]; msg.Envelope != nil && ok {
+ delete(store.pendingHeaders, msg.Uid)
+ }
+ update = true
break
}
+ if update && store.onUpdate != nil {
+ store.onUpdate(store)
+ }
+}
+
+func (store *MessageStore) OnUpdate(fn func(store *MessageStore)) {
+ store.onUpdate = fn
}
type MessageList struct {
@@ -47,15 +92,13 @@ type MessageList struct {
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 {
+func NewMessageList(logger *log.Logger) *MessageList {
ml := &MessageList{
logger: logger,
spinner: NewSpinner(),
- worker: worker,
}
ml.spinner.OnInvalidate(func(_ ui.Drawable) {
ml.Invalidate()
@@ -84,7 +127,7 @@ func (ml *MessageList) Draw(ctx *ui.Context) {
}
var (
- needsHeaders []uint64
+ needsHeaders []uint32
row int = 0
)
@@ -102,12 +145,11 @@ func (ml *MessageList) Draw(ctx *ui.Context) {
}
if len(needsHeaders) != 0 {
+ ml.store.FetchHeaders(needsHeaders)
ml.spinner.Start()
} else {
ml.spinner.Stop()
}
-
- // TODO: Fetch these messages
}
func (ml *MessageList) SetStore(store *MessageStore) {