Add display of unread messages in dirlist
Add an onUpdateDirs handler. This is used to invalidate the dirlist and redraw with the correct number of recent/unread/total messages is shown. A config option and formatting options are provided.
This commit is contained in:
parent
572d9ff728
commit
618a500341
5 changed files with 131 additions and 4 deletions
|
@ -43,6 +43,11 @@ mouse-enabled=false
|
|||
# Default: yes
|
||||
new-message-bell=true
|
||||
|
||||
# Describes the format string to use for the directory list
|
||||
#
|
||||
# Default: %n %>r
|
||||
dirlist-format=%n %>r
|
||||
|
||||
[viewer]
|
||||
#
|
||||
# Specifies the pager to use when displaying emails. Note that some filters
|
||||
|
|
|
@ -35,6 +35,7 @@ type UIConfig struct {
|
|||
NewMessageBell bool `ini:"new-message-bell"`
|
||||
Spinner string `ini:"spinner"`
|
||||
SpinnerDelimiter string `ini:"spinner-delimiter"`
|
||||
DirListFormat string `ini:"dirlist-format"`
|
||||
}
|
||||
|
||||
const (
|
||||
|
@ -349,9 +350,9 @@ func LoadConfigFromFile(root *string, sharedir string) (*AercConfig, error) {
|
|||
EmptyDirlist: "(no folders)",
|
||||
MouseEnabled: false,
|
||||
NewMessageBell: true,
|
||||
Spinner:
|
||||
"[..] , [..] , [..] , [..] , [..], [..] , [..] , [..] ",
|
||||
Spinner: "[..] , [..] , [..] , [..] , [..], [..] , [..] , [..] ",
|
||||
SpinnerDelimiter: ",",
|
||||
DirListFormat: "%n %>r",
|
||||
},
|
||||
|
||||
Viewer: ViewerConfig{
|
||||
|
|
|
@ -125,6 +125,22 @@ These options are configured in the *[ui]* section of aerc.conf.
|
|||
|
||||
Default: ","
|
||||
|
||||
*dirlist-format*
|
||||
Describes the format string to use for the directory list
|
||||
|
||||
Default: %n %>r
|
||||
|
||||
[- *Format specifier*
|
||||
:[ *Description*
|
||||
| %%
|
||||
: literal %
|
||||
| %n
|
||||
: directory name
|
||||
| %r
|
||||
: recent/unseen/total message count
|
||||
| %>X
|
||||
: make format specifier 'X' be right justified
|
||||
|
||||
## VIEWER
|
||||
|
||||
These options are configured in the *[viewer]* section of aerc.conf.
|
||||
|
|
|
@ -27,6 +27,7 @@ type MessageStore struct {
|
|||
|
||||
// Map of uids we've asked the worker to fetch
|
||||
onUpdate func(store *MessageStore) // TODO: multiple onUpdate handlers
|
||||
onUpdateDirs func()
|
||||
pendingBodies map[uint32]interface{}
|
||||
pendingHeaders map[uint32]interface{}
|
||||
worker *types.Worker
|
||||
|
@ -234,10 +235,17 @@ func (store *MessageStore) OnUpdate(fn func(store *MessageStore)) {
|
|||
store.onUpdate = fn
|
||||
}
|
||||
|
||||
func (store *MessageStore) OnUpdateDirs(fn func()) {
|
||||
store.onUpdateDirs = fn
|
||||
}
|
||||
|
||||
func (store *MessageStore) update() {
|
||||
if store.onUpdate != nil {
|
||||
store.onUpdate(store)
|
||||
}
|
||||
if store.onUpdateDirs != nil {
|
||||
store.onUpdateDirs()
|
||||
}
|
||||
}
|
||||
|
||||
func (store *MessageStore) Delete(uids []uint32,
|
||||
|
|
|
@ -1,15 +1,18 @@
|
|||
package widgets
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"regexp"
|
||||
"sort"
|
||||
|
||||
"github.com/gdamore/tcell"
|
||||
"github.com/mattn/go-runewidth"
|
||||
|
||||
"git.sr.ht/~sircmpwn/aerc/config"
|
||||
"git.sr.ht/~sircmpwn/aerc/lib"
|
||||
"git.sr.ht/~sircmpwn/aerc/lib/ui"
|
||||
"git.sr.ht/~sircmpwn/aerc/models"
|
||||
"git.sr.ht/~sircmpwn/aerc/worker/types"
|
||||
)
|
||||
|
||||
|
@ -105,6 +108,92 @@ func (dirlist *DirectoryList) Invalidate() {
|
|||
dirlist.DoInvalidate(dirlist)
|
||||
}
|
||||
|
||||
func (dirlist *DirectoryList) getDirString(name string, width int, recentUnseen func() string) string {
|
||||
percent := false
|
||||
rightJustify := false
|
||||
formatted := ""
|
||||
doRightJustify := func(s string) {
|
||||
formatted = runewidth.FillRight(formatted, width-len(s))
|
||||
formatted = runewidth.Truncate(formatted, width-len(s), "…")
|
||||
}
|
||||
for _, char := range dirlist.uiConf.DirListFormat {
|
||||
switch char {
|
||||
case '%':
|
||||
if percent {
|
||||
formatted += string(char)
|
||||
percent = false
|
||||
} else {
|
||||
percent = true
|
||||
}
|
||||
case '>':
|
||||
if percent {
|
||||
rightJustify = true
|
||||
}
|
||||
case 'n':
|
||||
if percent {
|
||||
if rightJustify {
|
||||
doRightJustify(name)
|
||||
rightJustify = false
|
||||
}
|
||||
formatted += name
|
||||
percent = false
|
||||
}
|
||||
case 'r':
|
||||
if percent {
|
||||
rString := recentUnseen()
|
||||
if rightJustify {
|
||||
doRightJustify(rString)
|
||||
rightJustify = false
|
||||
}
|
||||
formatted += rString
|
||||
percent = false
|
||||
}
|
||||
default:
|
||||
formatted += string(char)
|
||||
}
|
||||
}
|
||||
return formatted
|
||||
}
|
||||
|
||||
func (dirlist *DirectoryList) getRUEString(name string) string {
|
||||
totalUnseen := 0
|
||||
totalRecent := 0
|
||||
totalExists := 0
|
||||
if msgStore, ok := dirlist.MsgStore(name); ok {
|
||||
for _, msg := range msgStore.Messages {
|
||||
if msg == nil {
|
||||
continue
|
||||
}
|
||||
seen := false
|
||||
recent := false
|
||||
for _, flag := range msg.Flags {
|
||||
if flag == models.SeenFlag {
|
||||
seen = true
|
||||
} else if flag == models.RecentFlag {
|
||||
recent = true
|
||||
}
|
||||
}
|
||||
if !seen {
|
||||
if recent {
|
||||
totalRecent++
|
||||
} else {
|
||||
totalUnseen++
|
||||
}
|
||||
}
|
||||
}
|
||||
totalExists = msgStore.DirInfo.Exists
|
||||
}
|
||||
rueString := ""
|
||||
if totalRecent > 0 {
|
||||
rueString = fmt.Sprintf("%d/%d/%d", totalRecent, totalUnseen, totalExists)
|
||||
} else if totalUnseen > 0 {
|
||||
rueString = fmt.Sprintf("%d/%d", totalUnseen, totalExists)
|
||||
} else if totalExists > 0 {
|
||||
rueString = fmt.Sprintf("%d", totalExists)
|
||||
}
|
||||
return rueString
|
||||
}
|
||||
|
||||
func (dirlist *DirectoryList) Draw(ctx *ui.Context) {
|
||||
ctx.Fill(0, 0, ctx.Width(), ctx.Height(), ' ', tcell.StyleDefault)
|
||||
|
||||
|
@ -132,7 +221,12 @@ func (dirlist *DirectoryList) Draw(ctx *ui.Context) {
|
|||
style = style.Foreground(tcell.ColorGray)
|
||||
}
|
||||
ctx.Fill(0, row, ctx.Width(), 1, ' ', style)
|
||||
ctx.Printf(0, row, style, "%s", name)
|
||||
|
||||
dirString := dirlist.getDirString(name, ctx.Width(), func() string {
|
||||
return dirlist.getRUEString(name)
|
||||
})
|
||||
|
||||
ctx.Printf(0, row, style, dirString)
|
||||
row++
|
||||
}
|
||||
}
|
||||
|
@ -233,4 +327,7 @@ func (dirlist *DirectoryList) MsgStore(name string) (*lib.MessageStore, bool) {
|
|||
|
||||
func (dirlist *DirectoryList) SetMsgStore(name string, msgStore *lib.MessageStore) {
|
||||
dirlist.store.SetMessageStore(name, msgStore)
|
||||
msgStore.OnUpdateDirs(func() {
|
||||
dirlist.Invalidate()
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue