summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--widgets/msglist.go25
-rw-r--r--widgets/spinner.go2
-rw-r--r--worker/imap/fetch.go46
-rw-r--r--worker/imap/worker.go2
4 files changed, 71 insertions, 4 deletions
diff --git a/widgets/msglist.go b/widgets/msglist.go
index fef396b..22695ec 100644
--- a/widgets/msglist.go
+++ b/widgets/msglist.go
@@ -14,6 +14,8 @@ import (
 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{}
@@ -67,9 +69,11 @@ func (store *MessageStore) Update(msg types.WorkerMessage) {
 			}
 		}
 		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)
@@ -90,6 +94,7 @@ type MessageList struct {
 	conf         *config.AercConfig
 	logger       *log.Logger
 	onInvalidate func(d ui.Drawable)
+	selected     int
 	spinner      *Spinner
 	store        *MessageStore
 }
@@ -97,8 +102,9 @@ type MessageList struct {
 // TODO: fish in config
 func NewMessageList(logger *log.Logger) *MessageList {
 	ml := &MessageList{
-		logger:  logger,
-		spinner: NewSpinner(),
+		logger:   logger,
+		selected: 0,
+		spinner:  NewSpinner(),
 	}
 	ml.spinner.OnInvalidate(func(_ ui.Drawable) {
 		ml.Invalidate()
@@ -131,7 +137,10 @@ func (ml *MessageList) Draw(ctx *ui.Context) {
 		row          int = 0
 	)
 
-	for uid, msg := range ml.store.Messages {
+	for i := len(ml.store.Uids) - 1; i >= 0; i-- {
+		uid := ml.store.Uids[i]
+		msg := ml.store.Messages[uid]
+
 		if row >= ctx.Height() {
 			break
 		}
@@ -139,7 +148,17 @@ func (ml *MessageList) Draw(ctx *ui.Context) {
 		if msg == nil {
 			needsHeaders = append(needsHeaders, uid)
 			ml.spinner.Draw(ctx.Subcontext(0, row, ctx.Width(), 1))
+			row += 1
+			continue
+		}
+
+		style := tcell.StyleDefault
+		if row == ml.selected {
+			style = style.Background(tcell.ColorWhite).
+				Foreground(tcell.ColorBlack)
 		}
+		ctx.Fill(0, row, ctx.Width(), 1, ' ', style)
+		ctx.Printf(0, row, style, "%s", msg.Envelope.Subject)
 
 		row += 1
 	}
diff --git a/widgets/spinner.go b/widgets/spinner.go
index 812fb2c..bafc712 100644
--- a/widgets/spinner.go
+++ b/widgets/spinner.go
@@ -73,7 +73,7 @@ func (s *Spinner) IsRunning() bool {
 
 func (s *Spinner) Draw(ctx *ui.Context) {
 	if !s.IsRunning() {
-		return
+		s.Start()
 	}
 
 	ctx.Fill(0, 0, ctx.Width(), ctx.Height(), ' ', tcell.StyleDefault)
diff --git a/worker/imap/fetch.go b/worker/imap/fetch.go
new file mode 100644
index 0000000..383a8a8
--- /dev/null
+++ b/worker/imap/fetch.go
@@ -0,0 +1,46 @@
+package imap
+
+import (
+	"github.com/emersion/go-imap"
+
+	"git.sr.ht/~sircmpwn/aerc2/worker/types"
+)
+
+func (imapw *IMAPWorker) handleFetchMessageHeaders(
+	msg *types.FetchMessageHeaders) {
+
+	imapw.worker.Logger.Printf("Fetching message headers")
+
+	go func() {
+		messages := make(chan *imap.Message)
+		done := make(chan error, 1)
+		items := []imap.FetchItem{
+			imap.FetchEnvelope,
+			imap.FetchInternalDate,
+			imap.FetchFlags,
+			imap.FetchUid,
+		}
+		go func() {
+			done <- imapw.client.UidFetch(&msg.Uids, items, messages)
+		}()
+		go func() {
+			for msg := range messages {
+				imapw.worker.PostMessage(&types.MessageInfo{
+					Envelope:     msg.Envelope,
+					Flags:        msg.Flags,
+					InternalDate: msg.InternalDate,
+					Uid:          msg.Uid,
+				}, nil)
+			}
+			if err := <-done; err != nil {
+				imapw.worker.PostMessage(&types.Error{
+					Message: types.RespondTo(msg),
+					Error:   err,
+				}, nil)
+			} else {
+				imapw.worker.PostMessage(
+					&types.Done{types.RespondTo(msg)}, nil)
+			}
+		}()
+	}()
+}
diff --git a/worker/imap/worker.go b/worker/imap/worker.go
index 51cb221..1646165 100644
--- a/worker/imap/worker.go
+++ b/worker/imap/worker.go
@@ -154,6 +154,8 @@ func (w *IMAPWorker) handleMessage(msg types.WorkerMessage) error {
 		w.handleOpenDirectory(msg)
 	case *types.FetchDirectoryContents:
 		w.handleFetchDirectoryContents(msg)
+	case *types.FetchMessageHeaders:
+		w.handleFetchMessageHeaders(msg)
 	default:
 		return errUnsupported
 	}