~sircmpwn/aerc

Wire up threads backend for imap v1 PROPOSED

y0ast: 1
 Wire up threads backend for imap

 4 files changed, 65 insertions(+), 3 deletions(-)
Export patchset (mbox)
How do I use this?

Copy & paste the following snippet into your terminal to import this patchset into git:

curl -s https://lists.sr.ht/~sircmpwn/aerc/patches/14240/mbox | git am -3
Learn more about email & git
View this thread in the archives

[PATCH] Wire up threads backend for imap Export this patch

Add threaded message requests for imap based on go-imap-sortthread.

Co-authored-by: Kevin Kuehler <keur@xcf.berkeley.edu>
---
This patch depends on https://lists.sr.ht/~sircmpwn/aerc/patches/13893
(picking the go-imap 1.0.6 version in the conflict, or just run go mod
tidy).

I have a followup patch with a frontend, but since that patch is likely
a bit contentious I thought I would start with this and at least make some
progress towards supporting threads.

95%+ of the work here was done by Kevin, I just merged a few commits and
rebased it.

Let me know if you're ok with merging this, or if you prefer it in
the form of a patch set with the frontend.

 worker/imap/open.go      | 43 ++++++++++++++++++++++++++++++++++++++++
 worker/imap/worker.go    |  9 ++++++---
 worker/types/messages.go | 10 ++++++++++
 worker/types/thread.go   |  6 ++++++
 4 files changed, 65 insertions(+), 3 deletions(-)
 create mode 100644 worker/types/thread.go

diff --git a/worker/imap/open.go b/worker/imap/open.go
index 4605eb9..5d3b93b 100644
--- a/worker/imap/open.go
+++ b/worker/imap/open.go
@@ -95,3 +95,46 @@ func translageSortCriterions(
	}
	return result
}

func (imapw *IMAPWorker) handleDirectoryThreaded(
	msg *types.FetchDirectoryThreaded) {
	imapw.worker.Logger.Printf("Fetching threaded UID list")

	seqSet := &imap.SeqSet{}
	seqSet.AddRange(1, imapw.selected.Messages)
	threads, err := imapw.client.thread.UidThread(sortthread.References,
		&imap.SearchCriteria{SeqNum: seqSet})
	if err != nil {
		imapw.worker.PostMessage(&types.Error{
			Message: types.RespondTo(msg),
			Error:   err,
		}, nil)
	} else {
		aercThreads, count := convertThreads(threads)
		imapw.seqMap = make([]uint32, count)
		imapw.worker.PostMessage(&types.DirectoryThreaded{
			Message: types.RespondTo(msg),
			Threads: aercThreads,
		}, nil)
		imapw.worker.PostMessage(&types.Done{types.RespondTo(msg)}, nil)
	}
}

func convertThreads(threads []*sortthread.Thread) ([]*types.Thread, int) {
	if threads == nil {
		return nil, 0
	}
	conv := make([]*types.Thread, len(threads))
	count := 0

	for i := 0; i < len(threads); i++ {
		t := threads[i]
		children, childCount := convertThreads(t.Children)
		conv[i] = &types.Thread{
			Uid:      t.Id,
			Children: children,
		}
		count += childCount + 1
	}
	return conv, count
}
diff --git a/worker/imap/worker.go b/worker/imap/worker.go
index dab0afb..e48db2e 100644
--- a/worker/imap/worker.go
+++ b/worker/imap/worker.go
@@ -27,8 +27,9 @@ var errUnsupported = fmt.Errorf("unsupported command")

type imapClient struct {
	*client.Client
	idle *idle.IdleClient
	sort *sortthread.SortClient
	idle	 *idle.IdleClient
	thread   *sortthread.ThreadClient
	sort	 *sortthread.SortClient
}

type IMAPWorker struct {
@@ -157,7 +158,7 @@ func (w *IMAPWorker) handleMessage(msg types.WorkerMessage) error {
		}

		c.Updates = w.updates
		w.client = &imapClient{c, idle.NewClient(c), sortthread.NewSortClient(c)}
		w.client = &imapClient{c, idle.NewClient(c), sortthread.NewThreadClient(c), sortthread.NewSortClient(c)}
		w.worker.PostMessage(&types.Done{types.RespondTo(msg)}, nil)
	case *types.ListDirectories:
		w.handleListDirectories(msg)
@@ -165,6 +166,8 @@ func (w *IMAPWorker) handleMessage(msg types.WorkerMessage) error {
		w.handleOpenDirectory(msg)
	case *types.FetchDirectoryContents:
		w.handleFetchDirectoryContents(msg)
	case *types.FetchDirectoryThreaded:
		w.handleDirectoryThreaded(msg)
	case *types.CreateDirectory:
		w.handleCreateDirectory(msg)
	case *types.RemoveDirectory:
diff --git a/worker/types/messages.go b/worker/types/messages.go
index ab0e545..27fb131 100644
--- a/worker/types/messages.go
+++ b/worker/types/messages.go
@@ -81,11 +81,21 @@ type FetchDirectoryContents struct {
	SortCriteria []*SortCriterion
}

type FetchDirectoryThreaded struct {
	Message
	SortCriteria []*SortCriterion
}

type SearchDirectory struct {
	Message
	Argv []string
}

type DirectoryThreaded struct {
	Message
	Threads []*Thread
}

type CreateDirectory struct {
	Message
	Directory string
diff --git a/worker/types/thread.go b/worker/types/thread.go
new file mode 100644
index 0000000..265438f
--- /dev/null
+++ b/worker/types/thread.go
@@ -0,0 +1,6 @@
package types

type Thread struct {
	Uid      uint32
	Children []*Thread
}
-- 
2.28.0