aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorKoni Marti <koni.marti@gmail.com>2022-11-02 22:26:49 +0100
committerRobin Jarry <robin@jarry.cc>2022-11-06 23:16:39 +0100
commitdf0e7f7f9e484e2a41162cdf0e0b8725007e3b72 (patch)
tree5d76e4a6ba6d2cc3f6fc936511ada328052d97ee /lib
parent33ceb56680ba92406137ace7eee8139824446308 (diff)
downloadaerc-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.go7
-rw-r--r--lib/threadbuilder.go43
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)
}
}