k9s/internal/views/flash.go

145 lines
2.7 KiB
Go

package views
import (
"context"
"fmt"
"strings"
"time"
"github.com/derailed/k9s/internal/resource"
"github.com/derailed/tview"
"github.com/gdamore/tcell"
"github.com/rs/zerolog/log"
)
const (
flashInfo flashLevel = iota
flashWarn
flashErr
flashFatal
flashDelay = 3
emoDoh = "😗"
emoRed = "😡"
emoDead = "💀"
emoHappy = "😎"
)
type (
flashLevel int
flashView struct {
*tview.TextView
cancel context.CancelFunc
app *appView
}
)
func newFlashView(app *appView, m string) *flashView {
f := flashView{app: app, TextView: tview.NewTextView()}
f.SetTextColor(tcell.ColorAqua)
f.SetTextAlign(tview.AlignLeft)
f.SetBorderPadding(0, 0, 1, 1)
f.SetText("")
return &f
}
func (v *flashView) info(msg string) {
v.setMessage(flashInfo, msg)
}
func (v *flashView) infof(fmat string, args ...interface{}) {
v.info(fmt.Sprintf(fmat, args...))
}
func (v *flashView) warn(msg string) {
v.setMessage(flashWarn, msg)
}
func (v *flashView) warnf(fmat string, args ...interface{}) {
v.warn(fmt.Sprintf(fmat, args...))
}
func (v *flashView) err(err error) {
log.Error().Err(err).Msgf("%v", err)
v.setMessage(flashErr, err.Error())
}
func (v *flashView) errf(fmat string, args ...interface{}) {
var err error
for _, a := range args {
switch e := a.(type) {
case error:
err = e
}
}
log.Error().Err(err).Msgf(fmat, args...)
v.setMessage(flashErr, fmt.Sprintf(fmat, args...))
}
func (v *flashView) setMessage(level flashLevel, msg ...string) {
if v.cancel != nil {
v.cancel()
}
var ctx1, ctx2 context.Context
{
var timerCancel context.CancelFunc
ctx1, v.cancel = context.WithCancel(context.TODO())
ctx2, timerCancel = context.WithTimeout(context.TODO(), flashDelay*time.Second)
go v.refresh(ctx1, ctx2, timerCancel)
}
_, _, width, _ := v.GetRect()
if width <= 15 {
width = 100
}
m := strings.Join(msg, " ")
v.SetTextColor(flashColor(level))
v.SetText(resource.Truncate(flashEmoji(level)+" "+m, width-3))
}
func (v *flashView) refresh(ctx1, ctx2 context.Context, cancel context.CancelFunc) {
defer cancel()
for {
select {
// Timer canceled bail now
case <-ctx1.Done():
return
// Timed out clear and bail
case <-ctx2.Done():
v.app.QueueUpdateDraw(func() {
v.Clear()
v.app.Draw()
})
return
}
}
}
func flashEmoji(l flashLevel) string {
switch l {
case flashWarn:
return emoDoh
case flashErr:
return emoRed
case flashFatal:
return emoDead
default:
return emoHappy
}
}
func flashColor(l flashLevel) tcell.Color {
switch l {
case flashWarn:
return tcell.ColorOrange
case flashErr:
return tcell.ColorOrangeRed
case flashFatal:
return tcell.ColorFuchsia
default:
return tcell.ColorNavajoWhite
}
}