diff options
author | Koni Marti <koni.marti@gmail.com> | 2022-11-02 22:26:49 +0100 |
---|---|---|
committer | Robin Jarry <robin@jarry.cc> | 2022-11-06 23:16:39 +0100 |
commit | df0e7f7f9e484e2a41162cdf0e0b8725007e3b72 (patch) | |
tree | 5d76e4a6ba6d2cc3f6fc936511ada328052d97ee /lib | |
parent | 33ceb56680ba92406137ace7eee8139824446308 (diff) | |
download | aerc-df0e7f7f9e484e2a41162cdf0e0b8725007e3b72.tar.gz |
threadbuilder: sort siblings by sort criteria
Sort the client-side thread siblings according to the sort criteria.
Activate this option by setting "sort-thread-siblings" to true in the ui
section of aerc.conf. "sort-thread-siblings" is false by default and the
siblings will be sorted based on their uid number.
Note that this options will only work with client-side threading and
when the backend supports sorting. Also, it comes with a slight
performance penalty.
Signed-off-by: Koni Marti <koni.marti@gmail.com>
Acked-by: Tim Culverhouse <tim@timculverhouse.com>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/msgstore.go | 7 | ||||
-rw-r--r-- | lib/threadbuilder.go | 43 |
2 files changed, 41 insertions, 9 deletions
diff --git a/lib/msgstore.go b/lib/msgstore.go index a22e1961..bbda90dd 100644 --- a/lib/msgstore.go +++ b/lib/msgstore.go @@ -41,6 +41,7 @@ type MessageStore struct { threadedView bool reverseThreadOrder bool + sortThreadSiblings bool buildThreads bool builder *ThreadBuilder @@ -75,7 +76,7 @@ func NewMessageStore(worker *types.Worker, dirInfo *models.DirectoryInfo, defaultSortCriteria []*types.SortCriterion, thread bool, clientThreads bool, clientThreadsDelay time.Duration, - reverseOrder bool, reverseThreadOrder bool, + reverseOrder bool, reverseThreadOrder bool, sortThreadSiblings bool, triggerNewEmail func(*models.MessageInfo), triggerDirectoryChange func(), ) *MessageStore { @@ -95,6 +96,7 @@ func NewMessageStore(worker *types.Worker, threadedView: thread, buildThreads: clientThreads, reverseThreadOrder: reverseThreadOrder, + sortThreadSiblings: sortThreadSiblings, filter: []string{"filter"}, sortCriteria: defaultSortCriteria, @@ -434,7 +436,8 @@ func (store *MessageStore) runThreadBuilderNow() { } } // build new threads - th := store.builder.Threads(store.uids, store.reverseThreadOrder) + th := store.builder.Threads(store.uids, store.reverseThreadOrder, + store.sortThreadSiblings) // save local threads to the message store variable and // run callback if defined (callback should reposition cursor) diff --git a/lib/threadbuilder.go b/lib/threadbuilder.go index 52484162..6a32dd29 100644 --- a/lib/threadbuilder.go +++ b/lib/threadbuilder.go @@ -50,13 +50,15 @@ func (builder *ThreadBuilder) Update(msg *models.MessageInfo) { } // Threads returns a slice of threads for the given list of uids -func (builder *ThreadBuilder) Threads(uids []uint32, inverse bool) []*types.Thread { +func (builder *ThreadBuilder) Threads(uids []uint32, inverse bool, sort bool, +) []*types.Thread { builder.Lock() defer builder.Unlock() start := time.Now() - threads := builder.buildAercThreads(builder.generateStructure(uids), uids) + threads := builder.buildAercThreads(builder.generateStructure(uids), + uids, sort) // sort threads according to uid ordering builder.sortThreads(threads, uids) @@ -87,13 +89,38 @@ func (builder *ThreadBuilder) generateStructure(uids []uint32) jwz.Threadable { return threadStructure } -func (builder *ThreadBuilder) buildAercThreads(structure jwz.Threadable, uids []uint32) []*types.Thread { +func (builder *ThreadBuilder) buildAercThreads(structure jwz.Threadable, + uids []uint32, sort bool, +) []*types.Thread { threads := make([]*types.Thread, 0, len(builder.threadBlocks)) if structure == nil { for _, uid := range uids { threads = append(threads, &types.Thread{Uid: uid}) } } else { + + // prepare bigger function + var bigger func(l, r *types.Thread) bool + if sort { + sortMap := make(map[uint32]int) + for i, uid := range uids { + sortMap[uid] = i + } + bigger = func(left, right *types.Thread) bool { + if left == nil || right == nil { + return false + } + return sortMap[left.Uid] > sortMap[right.Uid] + } + } else { + bigger = func(left, right *types.Thread) bool { + if left == nil || right == nil { + return false + } + return left.Uid > right.Uid + } + } + // add uids for the unfetched messages for _, uid := range uids { if _, ok := builder.threadBlocks[uid]; !ok { @@ -103,7 +130,7 @@ func (builder *ThreadBuilder) buildAercThreads(structure jwz.Threadable, uids [] // build thread tree root := &types.Thread{Uid: 0} - builder.buildTree(structure, root) + builder.buildTree(structure, root, bigger) // copy top-level threads to thread slice for thread := root.FirstChild; thread != nil; thread = thread.NextSibling { @@ -116,7 +143,9 @@ func (builder *ThreadBuilder) buildAercThreads(structure jwz.Threadable, uids [] } // buildTree recursively translates the jwz threads structure into aerc threads -func (builder *ThreadBuilder) buildTree(c jwz.Threadable, parent *types.Thread) { +func (builder *ThreadBuilder) buildTree(c jwz.Threadable, parent *types.Thread, + bigger func(l, r *types.Thread) bool, +) { if c == nil || parent == nil { return } @@ -124,9 +153,9 @@ func (builder *ThreadBuilder) buildTree(c jwz.Threadable, parent *types.Thread) thread := parent if !node.IsDummy() { thread = builder.newThread(node, parent) - parent.OrderedInsert(thread) + parent.InsertCmp(thread, bigger) } - builder.buildTree(node.GetChild(), thread) + builder.buildTree(node.GetChild(), thread, bigger) } } |