about summary refs log tree commit diff stats
path: root/worker/imap/open.go
diff options
context:
space:
mode:
Diffstat (limited to 'worker/imap/open.go')
-rw-r--r--worker/imap/open.go49
1 files changed, 47 insertions, 2 deletions
diff --git a/worker/imap/open.go b/worker/imap/open.go
index 0602a7f..891b8a2 100644
--- a/worker/imap/open.go
+++ b/worker/imap/open.go
@@ -2,6 +2,7 @@ package imap
 
 import (
 	"github.com/emersion/go-imap"
+	sortthread "github.com/emersion/go-imap-sortthread"
 
 	"git.sr.ht/~sircmpwn/aerc/worker/types"
 )
@@ -30,9 +31,29 @@ func (imapw *IMAPWorker) handleFetchDirectoryContents(
 
 	seqSet := &imap.SeqSet{}
 	seqSet.AddRange(1, imapw.selected.Messages)
-	uids, err := imapw.client.UidSearch(&imap.SearchCriteria{
+
+	searchCriteria := &imap.SearchCriteria{
 		SeqNum: seqSet,
-	})
+	}
+	sortCriteria := translateSortCriterions(msg.SortCriteria)
+
+	var uids []uint32
+
+	// If the server supports the SORT extension, do the sorting server side
+	ok, err := imapw.client.sort.SupportSort()
+	if err == nil && ok && len(sortCriteria) > 0 {
+		uids, err = imapw.client.sort.UidSort(sortCriteria, searchCriteria)
+		// copy in reverse as msgList displays backwards
+		for i, j := 0, len(uids)-1; i < j; i, j = i+1, j-1 {
+			uids[i], uids[j] = uids[j], uids[i]
+		}
+	} else {
+		if err != nil {
+			// Non fatal, but we do want to print to get some debug info
+			imapw.worker.Logger.Printf("can't check for SORT support: %v", err)
+		}
+		uids, err = imapw.client.UidSearch(searchCriteria)
+	}
 	if err != nil {
 		imapw.worker.PostMessage(&types.Error{
 			Message: types.RespondTo(msg),
@@ -50,3 +71,27 @@ func (imapw *IMAPWorker) handleFetchDirectoryContents(
 		imapw.worker.PostMessage(&types.Done{types.RespondTo(msg)}, nil)
 	}
 }
+
+type sortFieldMapT map[types.SortField]sortthread.SortField
+
+// caution, incomplete mapping
+var sortFieldMap sortFieldMapT = sortFieldMapT{
+	types.SortArrival: sortthread.SortArrival,
+	types.SortCc:      sortthread.SortCc,
+	types.SortDate:    sortthread.SortDate,
+	types.SortFrom:    sortthread.SortFrom,
+	types.SortSize:    sortthread.SortSize,
+	types.SortSubject: sortthread.SortSubject,
+	types.SortTo:      sortthread.SortTo,
+}
+
+func translateSortCriterions(
+	cs []*types.SortCriterion) []sortthread.SortCriterion {
+	result := make([]sortthread.SortCriterion, 0, len(cs))
+	for _, c := range cs {
+		if f, ok := sortFieldMap[c.Field]; ok {
+			result = append(result, sortthread.SortCriterion{f, c.Reverse})
+		}
+	}
+	return result
+}