1
0
Fork 0
mirror of https://git.sr.ht/~rjarry/aerc synced 2025-02-22 23:23:57 +01:00
aerc/app/status.go
Jason Cox 6a84f1331f templates: add visual mode indicator to TrayInfo
It's useful to have some indicator of whether or not aerc is in visual
mark mode. Add such an indicator to the TrayInfo available in the status
line.

Changelog-changed: The `TrayInfo` template variable now includes a
 visual mark mode indicator.
Signed-off-by: Jason Cox <me@jasoncarloscox.com>
Acked-by: Robin Jarry <robin@jarry.cc>
2024-03-04 22:33:15 +01:00

165 lines
4 KiB
Go

package app
import (
"bytes"
"sync"
"time"
"github.com/mattn/go-runewidth"
"git.sr.ht/~rjarry/aerc/config"
"git.sr.ht/~rjarry/aerc/lib/log"
"git.sr.ht/~rjarry/aerc/lib/state"
"git.sr.ht/~rjarry/aerc/lib/templates"
"git.sr.ht/~rjarry/aerc/lib/ui"
"git.sr.ht/~rockorager/vaxis"
)
type StatusLine struct {
sync.Mutex
stack []*StatusMessage
acct *AccountView
err string
}
type StatusMessage struct {
style vaxis.Style
message string
}
func (status *StatusLine) Invalidate() {
ui.Invalidate()
}
func (status *StatusLine) Draw(ctx *ui.Context) {
status.Lock()
defer status.Unlock()
style := status.uiConfig().GetStyle(config.STYLE_STATUSLINE_DEFAULT)
ctx.Fill(0, 0, ctx.Width(), ctx.Height(), ' ', style)
switch {
case len(status.stack) != 0:
line := status.stack[len(status.stack)-1]
msg := runewidth.Truncate(line.message, ctx.Width(), "")
msg = runewidth.FillRight(msg, ctx.Width())
ctx.Printf(0, 0, line.style, "%s", msg)
case status.err != "":
msg := runewidth.Truncate(status.err, ctx.Width(), "")
msg = runewidth.FillRight(msg, ctx.Width())
style := status.uiConfig().GetStyle(config.STYLE_STATUSLINE_ERROR)
ctx.Printf(0, 0, style, "%s", msg)
case status.acct != nil:
data := state.NewDataSetter()
data.SetPendingKeys(aerc.pendingKeys)
data.SetState(&status.acct.state)
data.SetAccount(status.acct.acct)
data.SetFolder(status.acct.Directories().SelectedDirectory())
msg, _ := status.acct.SelectedMessage()
data.SetInfo(msg, 0, false)
data.SetRUE(status.acct.dirlist.List(), status.acct.dirlist.GetRUECount)
if store := status.acct.Store(); store != nil {
data.SetVisual(store.Marker().IsVisualMark())
}
table := ui.NewTable(
ctx.Height(),
config.Statusline.StatusColumns,
config.Statusline.ColumnSeparator,
nil,
func(*ui.Table, int) vaxis.Style { return style },
)
var buf bytes.Buffer
cells := make([]string, len(table.Columns))
for c, col := range table.Columns {
err := templates.Render(col.Def.Template, &buf,
data.Data())
if err != nil {
log.Errorf("%s", err)
cells[c] = err.Error()
} else {
cells[c] = buf.String()
}
buf.Reset()
}
table.AddRow(cells, nil)
table.Draw(ctx)
}
}
func (status *StatusLine) Update(acct *AccountView) {
status.acct = acct
status.Invalidate()
}
func (status *StatusLine) SetError(err string) {
prev := status.err
status.err = err
if prev != status.err {
status.Invalidate()
}
}
func (status *StatusLine) Clear() {
status.SetError("")
status.acct = nil
}
func (status *StatusLine) Push(text string, expiry time.Duration) *StatusMessage {
status.Lock()
defer status.Unlock()
log.Debugf(text)
msg := &StatusMessage{
style: status.uiConfig().GetStyle(config.STYLE_STATUSLINE_DEFAULT),
message: text,
}
status.stack = append(status.stack, msg)
go (func() {
defer log.PanicHandler()
time.Sleep(expiry)
status.Lock()
defer status.Unlock()
for i, m := range status.stack {
if m == msg {
status.stack = append(status.stack[:i], status.stack[i+1:]...)
break
}
}
status.Invalidate()
})()
status.Invalidate()
return msg
}
func (status *StatusLine) PushError(text string) *StatusMessage {
log.Errorf(text)
msg := status.Push(text, 10*time.Second)
msg.Color(status.uiConfig().GetStyle(config.STYLE_STATUSLINE_ERROR))
return msg
}
func (status *StatusLine) PushWarning(text string) *StatusMessage {
log.Warnf(text)
msg := status.Push(text, 10*time.Second)
msg.Color(status.uiConfig().GetStyle(config.STYLE_STATUSLINE_WARNING))
return msg
}
func (status *StatusLine) PushSuccess(text string) *StatusMessage {
log.Tracef(text)
msg := status.Push(text, 10*time.Second)
msg.Color(status.uiConfig().GetStyle(config.STYLE_STATUSLINE_SUCCESS))
return msg
}
func (status *StatusLine) Expire() {
status.Lock()
defer status.Unlock()
status.stack = nil
}
func (status *StatusLine) uiConfig() *config.UIConfig {
return SelectedAccountUiConfig()
}
func (msg *StatusMessage) Color(style vaxis.Style) {
msg.style = style
}