~rjarry/aerc-devel

This thread contains a patchset. You're looking at the original emails, but you may wish to use the patch review UI. Review patch
6 4

[PATCH aerc 0/2] Implement dummy threads for notmuch

Details
Message ID
<20240305231305.44287-4-julio.bacel@gmail.com>
DKIM signature
pass
Download raw message
Currently, threads that are incomplete are not drawn properly by aerc.
For example:

	Sender A	Re: test msg		01 Jan 01
	Sender B	Re: test msg		02 Jan 01
	Sender C	Re: test msg		03 Jan 01

Use the first message as a "dummy" root, and link the rest of the
messages to it. The above example becomes:

	Sender A	┬─>Re: test msg		01 Jan 01
	Sender B	├─>            		02 Jan 01
	Sender C	└─>            		03 Jan 01

Julio B (2):
  notmuch: draw incomplete threads
  ui: use a custom prefix for dummy root

 app/msglist.go                 |  6 +++++-
 config/aerc.conf               | 14 ++++++++++++++
 config/ui.go                   |  2 ++
 doc/aerc-config.5.scd          | 11 +++++++++++
 worker/notmuch/lib/database.go | 17 ++++++++++++-----
 worker/types/thread.go         |  3 +++
 6 files changed, 47 insertions(+), 6 deletions(-)

-- 
2.44.0

[PATCH aerc 1/2] notmuch: draw incomplete threads

Details
Message ID
<20240305231305.44287-5-julio.bacel@gmail.com>
In-Reply-To
<20240305231305.44287-4-julio.bacel@gmail.com> (view parent)
DKIM signature
pass
Download raw message
Patch: +11 -5
Create a "pseudo thread" with the first message as root. This is a
temporary solution, until we have a more generic implementation of dummy
messages that works for all backends.

Signed-off-by: Julio B <julio.bacel@gmail.com>
---
 worker/notmuch/lib/database.go | 16 +++++++++++-----
 1 file changed, 11 insertions(+), 5 deletions(-)

diff --git a/worker/notmuch/lib/database.go b/worker/notmuch/lib/database.go
index 4d853642..beddb38d 100644
--- a/worker/notmuch/lib/database.go
+++ b/worker/notmuch/lib/database.go
@@ -137,11 +137,17 @@ func (db *DB) ThreadsFromQuery(ctx context.Context, q string, entireThread bool)
			thread := threads.Thread()
			tlm := thread.TopLevelMessages()
			root := db.makeThread(nil, &tlm, entireThread)
			// if len(root) > 1 {
			// TODO make a dummy root node and link all the
			// first level children to it
			// }
			res = append(res, root...)
			if len(root) > 1 {
				root[0].FirstChild = root[0].NextSibling
				root[0].NextSibling.PrevSibling = nil
				root[0].NextSibling = nil
				for i := 1; i < len(root); i++ {
					root[i].Parent = root[0]
				}
				res = append(res, root[0])
			} else {
				res = append(res, root...)
			}
			tlm.Close()
			thread.Close()
		}
-- 
2.44.0

[PATCH aerc 2/2] ui: use a custom prefix for dummy root

Details
Message ID
<20240305231305.44287-6-julio.bacel@gmail.com>
In-Reply-To
<20240305231305.44287-4-julio.bacel@gmail.com> (view parent)
DKIM signature
pass
Download raw message
Patch: +36 -1
These messages are not really the root of the thread, and should not be
displayed as such. Add a new special prefix to make them appear like
the first child of a rootless thread.

Signed-off-by: Julio B <julio.bacel@gmail.com>
---

Notes:
    Before:         After:
    -------------------------------
    Re: subject     ┬─>Re: subject
    ├─>             ├─>
    └─>             └─>

 app/msglist.go                 |  6 +++++-
 config/aerc.conf               | 14 ++++++++++++++
 config/ui.go                   |  2 ++
 doc/aerc-config.5.scd          | 11 +++++++++++
 worker/notmuch/lib/database.go |  1 +
 worker/types/thread.go         |  3 +++
 6 files changed, 36 insertions(+), 1 deletion(-)

diff --git a/app/msglist.go b/app/msglist.go
index 4cdf614a..996ffa0c 100644
--- a/app/msglist.go
+++ b/app/msglist.go
@@ -438,7 +438,7 @@ func unreadInThread(thread *types.Thread, store *lib.MessageStore) (ctr int) {

func threadPrefix(t *types.Thread, reverse bool, msglist bool) string {
	uiConfig := SelectedAccountUiConfig()
	var tip, prefix, firstChild, lastSibling, orphan string
	var tip, prefix, firstChild, lastSibling, orphan, dummy string
	if msglist {
		tip = uiConfig.ThreadPrefixTip
	} else {
@@ -472,10 +472,12 @@ func threadPrefix(t *types.Thread, reverse bool, msglist bool) string {
		firstChild = uiConfig.ThreadPrefixFirstChildReverse
		lastSibling = uiConfig.ThreadPrefixLastSiblingReverse
		orphan = uiConfig.ThreadPrefixOrphanReverse
		dummy = uiConfig.ThreadPrefixDummyReverse
	} else {
		firstChild = uiConfig.ThreadPrefixFirstChild
		lastSibling = uiConfig.ThreadPrefixLastSibling
		orphan = uiConfig.ThreadPrefixOrphan
		dummy = uiConfig.ThreadPrefixDummy
	}

	var hiddenOffspring bool = t.FirstChild != nil && t.FirstChild.Hidden > 0
@@ -503,6 +505,8 @@ func threadPrefix(t *types.Thread, reverse bool, msglist bool) string {
			uiConfig.ThreadPrefixTip
	case t.Parent == nil && hiddenOffspring:
		prefix = uiConfig.ThreadPrefixFolded
	case t.Parent == nil && t.Dummy:
		prefix = dummy + tip
	case t.Parent == nil && t.FirstChild != nil:
		prefix = orphan
	case t.Parent == nil && t.FirstChild == nil:
diff --git a/config/aerc.conf b/config/aerc.conf
index 17b9d216..a6f287a1 100644
--- a/config/aerc.conf
+++ b/config/aerc.conf
@@ -477,6 +477,20 @@
# Default: "┌─"
#thread-prefix-last-sibling-reverse = "┌─"

#
# Customize the thread prefix appearance by selecting the connector for dummy
# thread.
#
# Default: "┬─"
#thread-prefix-dummy = "┬─"

#
# Customize the reversed thread prefix appearance by selecting the connector for
# dummy thread.
#
# Default: "┴─"
#thread-prefix-dummy-reverse = "┴─"

#
# Customize the reversed thread prefix appearance by selecting the first child
# connector.
diff --git a/config/ui.go b/config/ui.go
index a6034d46..7e2076c7 100644
--- a/config/ui.go
+++ b/config/ui.go
@@ -92,9 +92,11 @@ type UIConfig struct {
	ThreadPrefixLone               string `ini:"thread-prefix-lone" default:""`
	ThreadPrefixOrphan             string `ini:"thread-prefix-orphan" default:""`
	ThreadPrefixLastSibling        string `ini:"thread-prefix-last-sibling" default:"└─"`
	ThreadPrefixDummy              string `ini:"thread-prefix-dummy" default:"┬─"`
	ThreadPrefixLastSiblingReverse string `ini:"thread-prefix-last-sibling-reverse" default:"┌─"`
	ThreadPrefixFirstChildReverse  string `ini:"thread-prefix-first-child-reverse" default:""`
	ThreadPrefixOrphanReverse      string `ini:"thread-prefix-orphan-reverse" default:""`
	ThreadPrefixDummyReverse       string `ini:"thread-prefix-dummy-reverse" default:"┴─"`

	// Tab Templates
	TabTitleAccount  *template.Template `ini:"tab-title-account" default:"{{.Account}}"`
diff --git a/doc/aerc-config.5.scd b/doc/aerc-config.5.scd
index ea931675..c0f7c535 100644
--- a/doc/aerc-config.5.scd
+++ b/doc/aerc-config.5.scd
@@ -559,6 +559,16 @@ following configurable prefix parts:

	Default: _┌─_

*thread-prefix-dummy* = _<string>_
	Define the connector for the dummy head.

	Default: _┬─_

*thread-prefix-dummy-reverse* = _<string>_
	Define the connector for the dummy head in reversed threads.

	Default: _┴─_

*thread-prefix-first-child-reverse* = _<string>_

	Define the arrow appearance by selecting the first child connector in
@@ -613,6 +623,7 @@ thread-prefix-unfolded = ""
thread-prefix-first-child = "┬"
thread-prefix-has-siblings = "├"
thread-prefix-orphan = "┌"
thread-prefix-dummy = "┬"
thread-prefix-lone = " "
thread-prefix-last-sibling = "╰"
```
diff --git a/worker/notmuch/lib/database.go b/worker/notmuch/lib/database.go
index beddb38d..9dd48d78 100644
--- a/worker/notmuch/lib/database.go
+++ b/worker/notmuch/lib/database.go
@@ -138,6 +138,7 @@ func (db *DB) ThreadsFromQuery(ctx context.Context, q string, entireThread bool)
			tlm := thread.TopLevelMessages()
			root := db.makeThread(nil, &tlm, entireThread)
			if len(root) > 1 {
				root[0].Dummy = true
				root[0].FirstChild = root[0].NextSibling
				root[0].NextSibling.PrevSibling = nil
				root[0].NextSibling = nil
diff --git a/worker/types/thread.go b/worker/types/thread.go
index 8705ace1..a79a0b2d 100644
--- a/worker/types/thread.go
+++ b/worker/types/thread.go
@@ -18,6 +18,9 @@ type Thread struct {
	Hidden  int  // if this flag is not zero the message isn't rendered in the UI
	Deleted bool // if this flag is set the message was deleted

	// if this flag is set the message is the root of an incomplete thread
	Dummy bool

	// Context indicates the message doesn't match the mailbox / query but
	// is displayed for context
	Context bool
-- 
2.44.0

[aerc/patches] build success

builds.sr.ht <builds@sr.ht>
Details
Message ID
<CZM76MSREC0G.12JY20R0KERE9@fra02>
In-Reply-To
<20240305231305.44287-6-julio.bacel@gmail.com> (view parent)
DKIM signature
missing
Download raw message
aerc/patches: SUCCESS in 2m6s

[Implement dummy threads for notmuch][0] from [Julio B][1]

[0]: https://lists.sr.ht/~rjarry/aerc-devel/patches/50013
[1]: julio.bacel@gmail.com

✓ #1162508 SUCCESS aerc/patches/openbsd.yml     https://builds.sr.ht/~rjarry/job/1162508
✓ #1162507 SUCCESS aerc/patches/alpine-edge.yml https://builds.sr.ht/~rjarry/job/1162507
Details
Message ID
<D030ITM62RQ2.3SMKH7TZ8RS0L@sindominio.net>
In-Reply-To
<20240305231305.44287-4-julio.bacel@gmail.com> (view parent)
DKIM signature
pass
Download raw message
It works fine for level-1 siblings, but if you mix them with level-2,
you get disappearing messages (which is way worse than unthreaded
messages). As discussed over on irc, fixing the root to the first
message doesn't seem like the best solution. Probably, creating a fake
ancestor would be better.

Tested-By: inwit <inwit@sindominio.net>
Details
Message ID
<D0HSGTSEV7B6.G64Q0THKW380@gmail.com>
In-Reply-To
<D030ITM62RQ2.3SMKH7TZ8RS0L@sindominio.net> (view parent)
DKIM signature
pass
Download raw message
On Mon Mar 25, 2024 at 7:38 PM EET, inwit wrote:
> It works fine for level-1 siblings, but if you mix them with level-2,
> you get disappearing messages (which is way worse than unthreaded
> messages). As discussed over on irc, fixing the root to the first
> message doesn't seem like the best solution. Probably, creating a fake
> ancestor would be better.
>
> Tested-By: inwit <inwit@sindominio.net> 

Thank you inwit for testing this out! That's correct, some edge cases
are not handled properly with this patch. The solution seems to be much
more complex and requires changes deep down in the threading logic of
aerc. Unfortunately, I haven't achieved much with this yet. I'm not
familiar with the whole codebase and i couldn't fix this without
breaking the message list. This turned out to be more challenging than
I initially thought!

Applied: [PATCH aerc 0/2] Implement dummy threads for notmuch

Details
Message ID
<171303699151.143680.1234755858391451423@ringo>
In-Reply-To
<20240305231305.44287-4-julio.bacel@gmail.com> (view parent)
DKIM signature
pass
Download raw message
Julio B <julio.bacel@gmail.com> wrote:
> Currently, threads that are incomplete are not drawn properly by aerc.
> For example:
>
> 	Sender A	Re: test msg		01 Jan 01
> 	Sender B	Re: test msg		02 Jan 01
> 	Sender C	Re: test msg		03 Jan 01
>
> Use the first message as a "dummy" root, and link the rest of the
> messages to it. The above example becomes:
>
> 	Sender A	┬─>Re: test msg		01 Jan 01
> 	Sender B	├─>            		02 Jan 01
> 	Sender C	└─>            		03 Jan 01
>
> Julio B (2):
>   notmuch: draw incomplete threads
>   ui: use a custom prefix for dummy root

Acked-by: Robin Jarry <robin@jarry.cc>

Applied, thanks.

To git@git.sr.ht:~rjarry/aerc
   65332c233880..941e2e9e7de0  master -> master
Reply to thread Export thread (mbox)