aboutsummaryrefslogtreecommitdiffstats
path: root/worker
diff options
context:
space:
mode:
authorReto Brunner <reto@labrat.space>2020-09-12 15:05:02 +0200
committerReto Brunner <reto@labrat.space>2020-10-11 09:18:45 +0200
commitb6bcf89784605aa8baa982677de9d8d8ddbaa404 (patch)
tree532a17d2c5fbf67b1576ca718596e271b631b384 /worker
parentd8a75a5159eb9bf18e629be0598aaef5f90da7e4 (diff)
downloadaerc-b6bcf89784605aa8baa982677de9d8d8ddbaa404.tar.gz
imap: add sort support
Diffstat (limited to 'worker')
-rw-r--r--worker/imap/open.go49
-rw-r--r--worker/imap/worker.go4
2 files changed, 50 insertions, 3 deletions
diff --git a/worker/imap/open.go b/worker/imap/open.go
index 0602a7fa..891b8a23 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
+}
diff --git a/worker/imap/worker.go b/worker/imap/worker.go
index c016af66..dab0afb5 100644
--- a/worker/imap/worker.go
+++ b/worker/imap/worker.go
@@ -8,6 +8,7 @@ import (
"github.com/emersion/go-imap"
idle "github.com/emersion/go-imap-idle"
+ sortthread "github.com/emersion/go-imap-sortthread"
"github.com/emersion/go-imap/client"
"golang.org/x/oauth2"
@@ -27,6 +28,7 @@ var errUnsupported = fmt.Errorf("unsupported command")
type imapClient struct {
*client.Client
idle *idle.IdleClient
+ sort *sortthread.SortClient
}
type IMAPWorker struct {
@@ -155,7 +157,7 @@ func (w *IMAPWorker) handleMessage(msg types.WorkerMessage) error {
}
c.Updates = w.updates
- w.client = &imapClient{c, idle.NewClient(c)}
+ w.client = &imapClient{c, idle.NewClient(c), sortthread.NewSortClient(c)}
w.worker.PostMessage(&types.Done{types.RespondTo(msg)}, nil)
case *types.ListDirectories:
w.handleListDirectories(msg)