aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/msgstore.go86
-rw-r--r--widgets/account.go7
-rw-r--r--widgets/msglist.go86
3 files changed, 93 insertions, 86 deletions
diff --git a/lib/msgstore.go b/lib/msgstore.go
new file mode 100644
index 0000000..79e1977
--- /dev/null
+++ b/lib/msgstore.go
@@ -0,0 +1,86 @@
+package lib
+
+import (
+ "github.com/emersion/go-imap"
+
+ "git.sr.ht/~sircmpwn/aerc2/worker/types"
+)
+
+type MessageStore struct {
+ DirInfo types.DirectoryInfo
+ Messages map[uint32]*types.MessageInfo
+ // Ordered list of known UIDs
+ Uids []uint32
+ // 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(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[uint32]*types.MessageInfo)
+ for _, uid := range msg.Uids {
+ if msg, ok := store.Messages[uid]; ok {
+ newMap[uid] = msg
+ } else {
+ newMap[uid] = nil
+ }
+ }
+ store.Messages = newMap
+ store.Uids = msg.Uids
+ update = true
+ break
+ case *types.MessageInfo:
+ // TODO: merge message info into existing record, if applicable
+ 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
+}
diff --git a/widgets/account.go b/widgets/account.go
index 8716b11..6919c0e 100644
--- a/widgets/account.go
+++ b/widgets/account.go
@@ -8,6 +8,7 @@ import (
"github.com/gdamore/tcell"
"git.sr.ht/~sircmpwn/aerc2/config"
+ "git.sr.ht/~sircmpwn/aerc2/lib"
"git.sr.ht/~sircmpwn/aerc2/lib/ui"
"git.sr.ht/~sircmpwn/aerc2/worker"
"git.sr.ht/~sircmpwn/aerc2/worker/types"
@@ -23,7 +24,7 @@ type AccountView struct {
onInvalidate func(d ui.Drawable)
runCmd func(cmd string) error
msglist *MessageList
- msgStores map[string]*MessageStore
+ msgStores map[string]*lib.MessageStore
pendingKeys []config.KeyStroke
statusline *StatusLine
statusbar *ui.Stack
@@ -70,7 +71,7 @@ func NewAccountView(conf *config.AercConfig, acct *config.AccountConfig,
grid: grid,
logger: logger,
msglist: msglist,
- msgStores: make(map[string]*MessageStore),
+ msgStores: make(map[string]*lib.MessageStore),
runCmd: runCmd,
statusbar: statusbar,
statusline: statusline,
@@ -226,7 +227,7 @@ func (acct *AccountView) onMessage(msg types.WorkerMessage) {
if store, ok := acct.msgStores[msg.Name]; ok {
store.Update(msg)
} else {
- acct.msgStores[msg.Name] = NewMessageStore(acct.worker, msg)
+ acct.msgStores[msg.Name] = lib.NewMessageStore(acct.worker, msg)
}
case *types.DirectoryContents:
store := acct.msgStores[acct.dirlist.selected]
diff --git a/widgets/msglist.go b/widgets/msglist.go
index 5ba75a8..0fb919d 100644
--- a/widgets/msglist.go
+++ b/widgets/msglist.go
@@ -3,100 +3,20 @@ package widgets
import (
"log"
- "github.com/emersion/go-imap"
"github.com/gdamore/tcell"
"git.sr.ht/~sircmpwn/aerc2/config"
+ "git.sr.ht/~sircmpwn/aerc2/lib"
"git.sr.ht/~sircmpwn/aerc2/lib/ui"
- "git.sr.ht/~sircmpwn/aerc2/worker/types"
)
-type MessageStore struct {
- DirInfo types.DirectoryInfo
- Messages map[uint32]*types.MessageInfo
- // Ordered list of known UIDs
- Uids []uint32
- // 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(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[uint32]*types.MessageInfo)
- for _, uid := range msg.Uids {
- if msg, ok := store.Messages[uid]; ok {
- newMap[uid] = msg
- } else {
- newMap[uid] = nil
- }
- }
- store.Messages = newMap
- store.Uids = msg.Uids
- update = true
- break
- case *types.MessageInfo:
- // TODO: merge message info into existing record, if applicable
- 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 {
conf *config.AercConfig
logger *log.Logger
onInvalidate func(d ui.Drawable)
selected int
spinner *Spinner
- store *MessageStore
+ store *lib.MessageStore
}
// TODO: fish in config
@@ -171,7 +91,7 @@ func (ml *MessageList) Draw(ctx *ui.Context) {
}
}
-func (ml *MessageList) SetStore(store *MessageStore) {
+func (ml *MessageList) SetStore(store *lib.MessageStore) {
ml.store = store
if store != nil {
ml.spinner.Stop()