aboutsummaryrefslogtreecommitdiffstats
path: root/widgets
diff options
context:
space:
mode:
Diffstat (limited to 'widgets')
-rw-r--r--widgets/authinfo.go93
-rw-r--r--widgets/msgviewer.go41
2 files changed, 128 insertions, 6 deletions
diff --git a/widgets/authinfo.go b/widgets/authinfo.go
new file mode 100644
index 00000000..08795541
--- /dev/null
+++ b/widgets/authinfo.go
@@ -0,0 +1,93 @@
+package widgets
+
+import (
+ "fmt"
+
+ "git.sr.ht/~rjarry/aerc/config"
+ "git.sr.ht/~rjarry/aerc/lib/auth"
+ "git.sr.ht/~rjarry/aerc/lib/ui"
+ "github.com/gdamore/tcell/v2"
+ "github.com/mattn/go-runewidth"
+)
+
+type AuthInfo struct {
+ ui.Invalidatable
+ authdetails *auth.Details
+ showInfo bool
+ uiConfig config.UIConfig
+}
+
+func NewAuthInfo(auth *auth.Details, showInfo bool, uiConfig config.UIConfig) *AuthInfo {
+ return &AuthInfo{authdetails: auth, showInfo: showInfo, uiConfig: uiConfig}
+}
+
+func (a *AuthInfo) Draw(ctx *ui.Context) {
+ defaultStyle := a.uiConfig.GetStyle(config.STYLE_DEFAULT)
+ style := a.uiConfig.GetStyle(config.STYLE_DEFAULT)
+ ctx.Fill(0, 0, ctx.Width(), ctx.Height(), ' ', defaultStyle)
+ var text string
+ if a.authdetails == nil {
+ text = "(no header)"
+ ctx.Printf(0, 0, defaultStyle, text)
+ } else if a.authdetails.Err != nil {
+ style = a.uiConfig.GetStyle(config.STYLE_ERROR)
+ text = a.authdetails.Err.Error()
+ ctx.Printf(0, 0, style, text)
+ } else {
+ checkBounds := func(x int) bool {
+ if x < ctx.Width() {
+ return true
+ } else {
+ return false
+ }
+ }
+ setResult := func(result auth.Result) (string, tcell.Style) {
+ switch result {
+ case auth.ResultNone:
+ return "none", defaultStyle
+ case auth.ResultNeutral:
+ return "neutral", a.uiConfig.GetStyle(config.STYLE_WARNING)
+ case auth.ResultPolicy:
+ return "policy", a.uiConfig.GetStyle(config.STYLE_WARNING)
+ case auth.ResultPass:
+ return "✓", a.uiConfig.GetStyle(config.STYLE_SUCCESS)
+ case auth.ResultFail:
+ return "✗", a.uiConfig.GetStyle(config.STYLE_ERROR)
+ default:
+ return string(result), a.uiConfig.GetStyle(config.STYLE_ERROR)
+ }
+ }
+ x := 1
+ for i := 0; i < len(a.authdetails.Results); i++ {
+ if checkBounds(x) {
+ text, style := setResult(a.authdetails.Results[i])
+ if i > 0 {
+ text = " " + text
+ }
+ x += ctx.Printf(x, 0, style, text)
+ }
+ }
+ if a.showInfo {
+ infoText := ""
+ for i := 0; i < len(a.authdetails.Infos); i++ {
+ if i > 0 {
+ infoText += ","
+ }
+ infoText += a.authdetails.Infos[i]
+ if reason := a.authdetails.Reasons[i]; reason != "" {
+ infoText += reason
+ }
+ }
+ if checkBounds(x) && infoText != "" {
+ if trunc := ctx.Width() - x - 3; trunc > 0 {
+ text = runewidth.Truncate(infoText, trunc, "…")
+ x += ctx.Printf(x, 0, defaultStyle, fmt.Sprintf(" (%s)", text))
+ }
+ }
+ }
+ }
+}
+
+func (a *AuthInfo) Invalidate() {
+ a.DoInvalidate(a)
+}
diff --git a/widgets/msgviewer.go b/widgets/msgviewer.go
index c88c9817..98764672 100644
--- a/widgets/msgviewer.go
+++ b/widgets/msgviewer.go
@@ -17,6 +17,7 @@ import (
"git.sr.ht/~rjarry/aerc/config"
"git.sr.ht/~rjarry/aerc/lib"
+ "git.sr.ht/~rjarry/aerc/lib/auth"
"git.sr.ht/~rjarry/aerc/lib/format"
"git.sr.ht/~rjarry/aerc/lib/ui"
"git.sr.ht/~rjarry/aerc/logging"
@@ -61,13 +62,29 @@ func NewMessageViewer(acct *AccountView,
layout := hf.forMessage(msg.MessageInfo())
header, headerHeight := layout.grid(
func(header string) ui.Drawable {
- return &HeaderView{
+ hv := &HeaderView{
conf: conf,
Name: header,
Value: fmtHeader(msg.MessageInfo(), header,
acct.UiConfig().TimestampFormat),
uiConfig: acct.UiConfig(),
}
+ showInfo := false
+ if i := strings.IndexRune(header, '+'); i > 0 {
+ header = header[:i]
+ hv.Name = header
+ showInfo = true
+ }
+ if parser := auth.New(header); parser != nil {
+ details, err := parser(msg.MessageInfo().RFC822Headers, acct.AccountConfig().TrustedAuthRes)
+ if err != nil {
+ hv.Value = err.Error()
+ } else {
+ hv.ValueField = NewAuthInfo(details, showInfo, acct.UiConfig())
+ }
+ hv.Invalidate()
+ }
+ return hv
},
)
@@ -134,6 +151,10 @@ func fmtHeader(msg *models.MessageInfo, header string, timefmt string) string {
return "error: no envelope for this message"
}
+ if v := auth.New(header); v != nil {
+ return "Fetching.."
+ }
+
switch header {
case "From":
return format.FormatAddresses(msg.Envelope.From)
@@ -796,16 +817,20 @@ func (pv *PartViewer) Event(event tcell.Event) bool {
type HeaderView struct {
ui.Invalidatable
- conf *config.AercConfig
- Name string
- Value string
- uiConfig config.UIConfig
+ conf *config.AercConfig
+ Name string
+ Value string
+ ValueField ui.Drawable
+ uiConfig config.UIConfig
}
func (hv *HeaderView) Draw(ctx *ui.Context) {
name := hv.Name
size := runewidth.StringWidth(name + ":")
lim := ctx.Width() - size - 1
+ if lim <= 0 || ctx.Height() <= 0 {
+ return
+ }
value := runewidth.Truncate(" "+hv.Value, lim, "…")
vstyle := hv.uiConfig.GetStyle(config.STYLE_DEFAULT)
@@ -818,7 +843,11 @@ func (hv *HeaderView) Draw(ctx *ui.Context) {
ctx.Fill(0, 0, ctx.Width(), ctx.Height(), ' ', vstyle)
ctx.Printf(0, 0, hstyle, "%s:", name)
- ctx.Printf(size, 0, vstyle, "%s", value)
+ if hv.ValueField == nil {
+ ctx.Printf(size, 0, vstyle, "%s", value)
+ } else {
+ hv.ValueField.Draw(ctx.Subcontext(size, 0, lim, 1))
+ }
}
func (hv *HeaderView) Invalidate() {