summary refs log tree commit diff stats
path: root/lib
diff options
context:
space:
mode:
authorDrew DeVault <sir@cmpwn.com>2019-03-29 22:35:53 -0400
committerDrew DeVault <sir@cmpwn.com>2019-03-29 22:36:15 -0400
commit77ede6eb5a22a5407541ac587736189fcca0037f (patch)
tree45627c15f7087f91ed9881e776a566d440bd878e /lib
parent84e9853c1613f43f76bd46f0c1eb143d1db16ac2 (diff)
downloadaerc-77ede6eb5a22a5407541ac587736189fcca0037f.tar.gz
Add body fetching support code
Diffstat (limited to 'lib')
-rw-r--r--lib/msgstore.go77
1 files changed, 71 insertions, 6 deletions
diff --git a/lib/msgstore.go b/lib/msgstore.go
index 35c6606..be124df 100644
--- a/lib/msgstore.go
+++ b/lib/msgstore.go
@@ -2,6 +2,7 @@ package lib
 
 import (
 	"github.com/emersion/go-imap"
+	"github.com/mohamedattahri/mail"
 
 	"git.sr.ht/~sircmpwn/aerc2/worker/types"
 )
@@ -11,6 +12,10 @@ type MessageStore struct {
 	Messages map[uint32]*types.MessageInfo
 	// Ordered list of known UIDs
 	Uids []uint32
+
+	bodyCallbacks   map[uint32][]func(*mail.Message)
+	headerCallbacks map[uint32][]func(*types.MessageInfo)
+
 	// Map of uids we've asked the worker to fetch
 	onUpdate       func(store *MessageStore) // TODO: multiple onUpdate handlers
 	pendingBodies  map[uint32]interface{}
@@ -24,13 +29,18 @@ func NewMessageStore(worker *types.Worker,
 	return &MessageStore{
 		DirInfo: *dirInfo,
 
+		bodyCallbacks:   make(map[uint32][]func(*mail.Message)),
+		headerCallbacks: make(map[uint32][]func(*types.MessageInfo)),
+
 		pendingBodies:  make(map[uint32]interface{}),
 		pendingHeaders: make(map[uint32]interface{}),
 		worker:         worker,
 	}
 }
 
-func (store *MessageStore) FetchHeaders(uids []uint32) {
+func (store *MessageStore) FetchHeaders(uids []uint32,
+	cb func(*types.MessageInfo)) {
+
 	// 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
@@ -38,12 +48,50 @@ func (store *MessageStore) FetchHeaders(uids []uint32) {
 		if _, ok := store.pendingHeaders[uid]; !ok {
 			toFetch.AddNum(uint32(uid))
 			store.pendingHeaders[uid] = nil
+			if cb != nil {
+				if list, ok := store.headerCallbacks[uid]; ok {
+					store.headerCallbacks[uid] = append(list, cb)
+				} else {
+					store.headerCallbacks[uid] = []func(*types.MessageInfo){cb}
+				}
+			}
+		}
+	}
+	if !toFetch.Empty() {
+		store.worker.PostAction(&types.FetchMessageHeaders{Uids: toFetch}, nil)
+	}
+}
+
+func (store *MessageStore) FetchBodies(uids []uint32,
+	cb func(*mail.Message)) {
+
+	// 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.pendingBodies[uid]; !ok {
+			toFetch.AddNum(uint32(uid))
+			store.pendingBodies[uid] = nil
+			if cb != nil {
+				if list, ok := store.bodyCallbacks[uid]; ok {
+					store.bodyCallbacks[uid] = append(list, cb)
+				} else {
+					store.bodyCallbacks[uid] = []func(*mail.Message){cb}
+				}
+			}
 		}
 	}
 	if !toFetch.Empty() {
-		store.worker.PostAction(&types.FetchMessageHeaders{
-			Uids: toFetch,
-		}, nil)
+		store.worker.PostAction(&types.FetchMessageBodies{Uids: toFetch}, nil)
+	}
+}
+
+func (store *MessageStore) merge(
+	to *types.MessageInfo, from *types.MessageInfo) {
+
+	// TODO: Merge more shit
+	if from.Envelope != nil {
+		to.Envelope = from.Envelope
 	}
 }
 
@@ -66,12 +114,29 @@ func (store *MessageStore) Update(msg types.WorkerMessage) {
 		store.Uids = msg.Uids
 		update = true
 	case *types.MessageInfo:
-		// TODO: merge message info into existing record, if applicable
-		store.Messages[msg.Uid] = msg
+		if existing, ok := store.Messages[msg.Uid]; ok && existing != nil {
+			store.merge(existing, msg)
+		} else {
+			store.Messages[msg.Uid] = msg
+		}
 		if _, ok := store.pendingHeaders[msg.Uid]; msg.Envelope != nil && ok {
 			delete(store.pendingHeaders, msg.Uid)
+			if cbs, ok := store.headerCallbacks[msg.Uid]; ok {
+				for _, cb := range cbs {
+					cb(msg)
+				}
+			}
 		}
 		update = true
+	case *types.MessageBody:
+		if _, ok := store.pendingBodies[msg.Uid]; ok {
+			delete(store.pendingBodies, msg.Uid)
+			if cbs, ok := store.bodyCallbacks[msg.Uid]; ok {
+				for _, cb := range cbs {
+					cb(msg.Mail)
+				}
+			}
+		}
 	case *types.MessagesDeleted:
 		toDelete := make(map[uint32]interface{})
 		for _, uid := range msg.Uids {
6:22 -0800 4777' href='/akkartik/mu/commit/subx/opcodes?h=hlt&id=f15fcfe8227a62103c0c62c33faaa424c75f0a48'>f15fcfe8 ^
bb3ce6cd ^





4c3a867b ^

15655a12 ^

4c3a867b ^





417a05ee ^
bb3ce6cd ^


f13576b5 ^
bb3ce6cd ^









924ed08a ^
417a05ee ^


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132