diff options
Diffstat (limited to 'widgets')
-rw-r--r-- | widgets/authinfo.go | 93 | ||||
-rw-r--r-- | widgets/msgviewer.go | 41 |
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() { |