diff options
author | y0ast <joost@joo.st> | 2021-11-12 18:12:02 +0100 |
---|---|---|
committer | Robin Jarry <robin@jarry.cc> | 2021-11-13 15:05:59 +0100 |
commit | dc2a2c2dfd6dc327fe40fbf2da922ef6c3d520be (patch) | |
tree | 4987160692aca01e27b068cb256d66d373556a52 /lib | |
parent | c303b953360994966ff657c4e17670853198ecf7 (diff) | |
download | aerc-dc2a2c2dfd6dc327fe40fbf2da922ef6c3d520be.tar.gz |
messages: allow displaying email threads
Display threads in the message list. For now, only supported by the
notmuch backend and on IMAP when the server supports the THREAD
extension.
Setting threading-enable=true is global and will cause the message list
to be empty with maildir:// accounts.
Co-authored-by: Kevin Kuehler <keur@xcf.berkeley.edu>
Co-authored-by: Reto Brunner <reto@labrat.space>
Signed-off-by: Robin Jarry <robin@jarry.cc>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/format/format.go | 12 | ||||
-rw-r--r-- | lib/msgstore.go | 55 |
2 files changed, 61 insertions, 6 deletions
diff --git a/lib/format/format.go b/lib/format/format.go index 8681de8e..59b5c479 100644 --- a/lib/format/format.go +++ b/lib/format/format.go @@ -45,6 +45,10 @@ type Ctx struct { MsgNum int MsgInfo *models.MessageInfo MsgIsMarked bool + + // UI controls for threading + ThreadPrefix string + ThreadSameSubject bool } func ParseMessageFormat(format string, timeFmt string, thisDayTimeFmt string, @@ -213,7 +217,13 @@ func ParseMessageFormat(format string, timeFmt string, thisDayTimeFmt string, args = append(args, addrs) case 's': retval = append(retval, 's') - args = append(args, envelope.Subject) + // if we are threaded strip the repeated subjects unless it's the + // first on the screen + subject := envelope.Subject + if ctx.ThreadSameSubject { + subject = "" + } + args = append(args, ctx.ThreadPrefix+subject) case 't': if len(envelope.To) == 0 { return "", nil, diff --git a/lib/msgstore.go b/lib/msgstore.go index b1faa738..40720b46 100644 --- a/lib/msgstore.go +++ b/lib/msgstore.go @@ -17,7 +17,8 @@ type MessageStore struct { Sorting bool // Ordered list of known UIDs - uids []uint32 + uids []uint32 + Threads []*types.Thread selected int bodyCallbacks map[uint32][]func(*types.FullMessage) @@ -35,6 +36,8 @@ type MessageStore struct { defaultSortCriteria []*types.SortCriterion + thread bool + // Map of uids we've asked the worker to fetch onUpdate func(store *MessageStore) // TODO: multiple onUpdate handlers onUpdateDirs func() @@ -52,6 +55,7 @@ type MessageStore struct { func NewMessageStore(worker *types.Worker, dirInfo *models.DirectoryInfo, defaultSortCriteria []*types.SortCriterion, + thread bool, triggerNewEmail func(*models.MessageInfo), triggerDirectoryChange func()) *MessageStore { @@ -67,6 +71,8 @@ func NewMessageStore(worker *types.Worker, bodyCallbacks: make(map[uint32][]func(*types.FullMessage)), headerCallbacks: make(map[uint32][]func(*types.MessageInfo)), + thread: thread, + defaultSortCriteria: defaultSortCriteria, pendingBodies: make(map[uint32]interface{}), @@ -189,6 +195,27 @@ func (store *MessageStore) Update(msg types.WorkerMessage) { store.Messages = newMap store.uids = msg.Uids update = true + case *types.DirectoryThreaded: + var uids []uint32 + newMap := make(map[uint32]*models.MessageInfo) + + for i := len(msg.Threads) - 1; i >= 0; i-- { + msg.Threads[i].Walk(func(t *types.Thread, level int, currentErr error) error { + uid := t.Uid + uids = append([]uint32{uid}, uids...) + if msg, ok := store.Messages[uid]; ok { + newMap[uid] = msg + } else { + newMap[uid] = nil + directoryChange = true + } + return nil + }) + } + store.Messages = newMap + store.uids = uids + store.Threads = msg.Threads + update = true case *types.MessageInfo: if existing, ok := store.Messages[msg.Info.Uid]; ok && existing != nil { merge(existing, msg.Info) @@ -257,6 +284,15 @@ func (store *MessageStore) Update(msg types.WorkerMessage) { } store.results = newResults + for _, thread := range store.Threads { + thread.Walk(func(t *types.Thread, _ int, _ error) error { + if _, deleted := toDelete[t.Uid]; deleted { + t.Deleted = true + } + return nil + }) + } + update = true } @@ -592,14 +628,23 @@ func (store *MessageStore) ModifyLabels(uids []uint32, add, remove []string, func (store *MessageStore) Sort(criteria []*types.SortCriterion, cb func()) { store.Sorting = true - store.worker.PostAction(&types.FetchDirectoryContents{ - SortCriteria: criteria, - }, func(_ types.WorkerMessage) { + + handle_return := func(msg types.WorkerMessage) { store.Sorting = false if cb != nil { cb() } - }) + } + + if store.thread { + store.worker.PostAction(&types.FetchDirectoryThreaded{ + SortCriteria: criteria, + }, handle_return) + } else { + store.worker.PostAction(&types.FetchDirectoryContents{ + SortCriteria: criteria, + }, handle_return) + } } // returns the index of needle in haystack or -1 if not found |