about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorStephen Brennan <stephen@brennan.io>2019-08-27 21:54:28 -0700
committerDrew DeVault <sir@cmpwn.com>2019-08-29 08:44:08 +0900
commitac99d9ed62644cf0259bdd79481b28c3fbcef650 (patch)
tree3c71dda62e9b2cd8f27d03d3af4edf6dbbae6e36
parenta2c5233f71522c894b90388623959dcd4cd44256 (diff)
downloadaerc-ac99d9ed62644cf0259bdd79481b28c3fbcef650.tar.gz
Fix out-of-order messages by sorting as we display
Sometimes I observe out-of-order messages when using a maildir inbox. It
appears that the UIDs for these messages are returned out of order by
the MessageStore. In order for a maildir MessageStore to return messages
in most recently received order, it must have already opened all
messages and parsed the date to use as a sort key. Rather than implement
that, simply sort messages by time as we display. This fix shows my
emails in order.
-rw-r--r--lib/msgstore.go2
-rw-r--r--widgets/msglist.go31
2 files changed, 32 insertions, 1 deletions
diff --git a/lib/msgstore.go b/lib/msgstore.go
index 1061c8e..169d51d 100644
--- a/lib/msgstore.go
+++ b/lib/msgstore.go
@@ -15,7 +15,7 @@ type MessageStore struct {
 	Deleted  map[uint32]interface{}
 	DirInfo  models.DirectoryInfo
 	Messages map[uint32]*models.MessageInfo
-	// Ordered list of known UIDs
+	// List of known UIDs, order is not important
 	uids []uint32
 
 	selected        int
diff --git a/widgets/msglist.go b/widgets/msglist.go
index 9900a32..df83dbd 100644
--- a/widgets/msglist.go
+++ b/widgets/msglist.go
@@ -3,6 +3,7 @@ package widgets
 import (
 	"fmt"
 	"log"
+	"sort"
 
 	"github.com/gdamore/tcell"
 	"github.com/mattn/go-runewidth"
@@ -26,6 +27,34 @@ type MessageList struct {
 	isInitalizing bool
 }
 
+type msgSorter struct {
+	uids []uint32
+	store *lib.MessageStore
+}
+
+func (s *msgSorter) Len() int {
+	return len(s.uids)
+}
+
+func (s *msgSorter) Less(i, j int) bool {
+	msgI := s.store.Messages[s.uids[i]]
+	msgJ := s.store.Messages[s.uids[j]]
+	if msgI == nil && msgJ == nil {
+		return false; // doesn't matter which order among nulls
+	} else if msgI == nil && msgJ != nil {
+		return true // say i is before j so we sort i to bottom
+	} else if msgI != nil && msgJ == nil {
+		return false // say i is after j so we sort j to bottom
+	}
+	return msgI.InternalDate.Before(msgJ.InternalDate)
+}
+
+func (s *msgSorter) Swap(i, j int) {
+	tmp := s.uids[i]
+	s.uids[i] = s.uids[j]
+	s.uids[j] = tmp
+}
+
 func NewMessageList(conf *config.AercConfig, logger *log.Logger) *MessageList {
 	ml := &MessageList{
 		conf:          conf,
@@ -66,6 +95,8 @@ func (ml *MessageList) Draw(ctx *ui.Context) {
 		row          int = 0
 	)
 	uids := store.Uids()
+	sorter := msgSorter{uids: uids, store: store}
+	sort.Sort(&sorter)
 
 	for i := len(uids) - 1 - ml.scroll; i >= 0; i-- {
 		uid := uids[i]