msglist: display reversed thread ordering
Reverse the ordering of the message threads. Implements: https://todo.sr.ht/~rjarry/aerc/54 Signed-off-by: Koni Marti <koni.marti@gmail.com> Acked-by: Robin Jarry <robin@jarry.cc>
This commit is contained in:
parent
006e10357b
commit
ae99f4c5bb
2 changed files with 65 additions and 56 deletions
|
@ -249,7 +249,7 @@ func (dt *DirectoryTree) countVisible(list []*types.Thread) (n int) {
|
||||||
|
|
||||||
func (dt *DirectoryTree) displayText(node *types.Thread) string {
|
func (dt *DirectoryTree) displayText(node *types.Thread) string {
|
||||||
elems := strings.Split(dt.treeDirs[getAnyUid(node)], dt.pathSeparator)
|
elems := strings.Split(dt.treeDirs[getAnyUid(node)], dt.pathSeparator)
|
||||||
return fmt.Sprintf("%s%s%s", threadPrefix(node), getFlag(node), elems[countLevels(node)])
|
return fmt.Sprintf("%s%s%s", threadPrefix(node, false), getFlag(node), elems[countLevels(node)])
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dt *DirectoryTree) getDirectory(node *types.Thread) string {
|
func (dt *DirectoryTree) getDirectory(node *types.Thread) string {
|
||||||
|
|
|
@ -12,6 +12,7 @@ import (
|
||||||
"git.sr.ht/~rjarry/aerc/config"
|
"git.sr.ht/~rjarry/aerc/config"
|
||||||
"git.sr.ht/~rjarry/aerc/lib"
|
"git.sr.ht/~rjarry/aerc/lib"
|
||||||
"git.sr.ht/~rjarry/aerc/lib/format"
|
"git.sr.ht/~rjarry/aerc/lib/format"
|
||||||
|
"git.sr.ht/~rjarry/aerc/lib/iterator"
|
||||||
"git.sr.ht/~rjarry/aerc/lib/ui"
|
"git.sr.ht/~rjarry/aerc/lib/ui"
|
||||||
"git.sr.ht/~rjarry/aerc/logging"
|
"git.sr.ht/~rjarry/aerc/logging"
|
||||||
"git.sr.ht/~rjarry/aerc/models"
|
"git.sr.ht/~rjarry/aerc/models"
|
||||||
|
@ -88,57 +89,61 @@ func (ml *MessageList) Draw(ctx *ui.Context) {
|
||||||
row int = 0
|
row int = 0
|
||||||
)
|
)
|
||||||
|
|
||||||
if store.ThreadedView() {
|
createBaseCtx := func(uid uint32, row int) format.Ctx {
|
||||||
iter := store.ThreadsIterator()
|
return format.Ctx{
|
||||||
var i int = 0
|
FromAddress: acct.acct.From,
|
||||||
|
AccountName: acct.Name(),
|
||||||
for iter.Next() {
|
MsgInfo: store.Messages[uid],
|
||||||
thread := iter.Value().(*types.Thread)
|
MsgNum: row,
|
||||||
var lastSubject string
|
MsgIsMarked: store.Marker().IsMarked(uid),
|
||||||
err := thread.Walk(func(t *types.Thread, _ int, currentErr error) error {
|
|
||||||
if currentErr != nil {
|
|
||||||
return currentErr
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if store.ThreadedView() {
|
||||||
|
var (
|
||||||
|
lastSubject string
|
||||||
|
prevThread *types.Thread
|
||||||
|
i int = 0
|
||||||
|
)
|
||||||
|
factory := iterator.NewFactory(!store.ReverseThreadOrder())
|
||||||
|
threadLoop:
|
||||||
|
for iter := store.ThreadsIterator(); iter.Next(); {
|
||||||
|
var cur []*types.Thread
|
||||||
|
err := iter.Value().(*types.Thread).Walk(
|
||||||
|
func(t *types.Thread, _ int, _ error,
|
||||||
|
) error {
|
||||||
if t.Hidden || t.Deleted {
|
if t.Hidden || t.Deleted {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if i < ml.Scroll() {
|
cur = append(cur, t)
|
||||||
i++
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
i++
|
|
||||||
msg := store.Messages[t.Uid]
|
|
||||||
var prefix string
|
|
||||||
var subject string
|
|
||||||
var normalizedSubject string
|
|
||||||
if msg != nil {
|
|
||||||
prefix = threadPrefix(t)
|
|
||||||
if msg.Envelope != nil {
|
|
||||||
subject = msg.Envelope.Subject
|
|
||||||
normalizedSubject, _ = sortthread.GetBaseSubject(subject)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fmtCtx := format.Ctx{
|
|
||||||
FromAddress: acct.acct.From,
|
|
||||||
AccountName: acct.Name(),
|
|
||||||
MsgInfo: msg,
|
|
||||||
MsgNum: row,
|
|
||||||
MsgIsMarked: store.Marker().IsMarked(t.Uid),
|
|
||||||
ThreadPrefix: prefix,
|
|
||||||
ThreadSameSubject: normalizedSubject == lastSubject,
|
|
||||||
}
|
|
||||||
if ml.drawRow(textWidth, ctx, t.Uid, row, &needsHeaders, fmtCtx) {
|
|
||||||
return types.ErrSkipThread
|
|
||||||
}
|
|
||||||
lastSubject = normalizedSubject
|
|
||||||
row++
|
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logging.Warnf("failed to walk threads: %v", err)
|
logging.Errorf("thread walk: %v", err)
|
||||||
|
}
|
||||||
|
for curIter := factory.NewIterator(cur); curIter.Next(); {
|
||||||
|
if i < ml.Scroll() {
|
||||||
|
i++
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if thread := curIter.Value().(*types.Thread); thread != nil {
|
||||||
|
fmtCtx := createBaseCtx(thread.Uid, row)
|
||||||
|
fmtCtx.ThreadPrefix = threadPrefix(thread,
|
||||||
|
store.ReverseThreadOrder())
|
||||||
|
if fmtCtx.MsgInfo != nil && fmtCtx.MsgInfo.Envelope != nil {
|
||||||
|
baseSubject, _ := sortthread.GetBaseSubject(
|
||||||
|
fmtCtx.MsgInfo.Envelope.Subject)
|
||||||
|
fmtCtx.ThreadSameSubject = baseSubject == lastSubject &&
|
||||||
|
sameParent(thread, prevThread) &&
|
||||||
|
!isParent(thread)
|
||||||
|
lastSubject = baseSubject
|
||||||
|
prevThread = thread
|
||||||
|
}
|
||||||
|
if ml.drawRow(textWidth, ctx, thread.Uid, row, &needsHeaders, fmtCtx) {
|
||||||
|
break threadLoop
|
||||||
|
}
|
||||||
|
row += 1
|
||||||
}
|
}
|
||||||
if row >= ctx.Height() {
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -148,15 +153,7 @@ func (ml *MessageList) Draw(ctx *ui.Context) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
uid := iter.Value().(uint32)
|
uid := iter.Value().(uint32)
|
||||||
|
fmtCtx := createBaseCtx(uid, row)
|
||||||
msg := store.Messages[uid]
|
|
||||||
fmtCtx := format.Ctx{
|
|
||||||
FromAddress: acct.acct.From,
|
|
||||||
AccountName: acct.Name(),
|
|
||||||
MsgInfo: msg,
|
|
||||||
MsgNum: row,
|
|
||||||
MsgIsMarked: store.Marker().IsMarked(uid),
|
|
||||||
}
|
|
||||||
if ml.drawRow(textWidth, ctx, uid, row, &needsHeaders, fmtCtx) {
|
if ml.drawRow(textWidth, ctx, uid, row, &needsHeaders, fmtCtx) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -429,15 +426,19 @@ func (ml *MessageList) drawEmptyMessage(ctx *ui.Context) {
|
||||||
uiConfig.GetStyle(config.STYLE_MSGLIST_DEFAULT), "%s", msg)
|
uiConfig.GetStyle(config.STYLE_MSGLIST_DEFAULT), "%s", msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
func threadPrefix(t *types.Thread) string {
|
func threadPrefix(t *types.Thread, reverse bool) string {
|
||||||
var arrow string
|
var arrow string
|
||||||
if t.Parent != nil {
|
if t.Parent != nil {
|
||||||
if t.NextSibling != nil {
|
if t.NextSibling != nil {
|
||||||
arrow = "├─>"
|
arrow = "├─>"
|
||||||
|
} else {
|
||||||
|
if reverse {
|
||||||
|
arrow = "┌─>"
|
||||||
} else {
|
} else {
|
||||||
arrow = "└─>"
|
arrow = "└─>"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
var prefix []string
|
var prefix []string
|
||||||
for n := t; n.Parent != nil; n = n.Parent {
|
for n := t; n.Parent != nil; n = n.Parent {
|
||||||
if n.Parent.NextSibling != nil {
|
if n.Parent.NextSibling != nil {
|
||||||
|
@ -458,3 +459,11 @@ func threadPrefix(t *types.Thread) string {
|
||||||
ps := strings.Join(prefix, "")
|
ps := strings.Join(prefix, "")
|
||||||
return fmt.Sprintf("%v%v", ps, arrow)
|
return fmt.Sprintf("%v%v", ps, arrow)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func sameParent(left, right *types.Thread) bool {
|
||||||
|
return left.Root() == right.Root()
|
||||||
|
}
|
||||||
|
|
||||||
|
func isParent(t *types.Thread) bool {
|
||||||
|
return t == t.Root()
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue