forked from derailed/k9s
-
Notifications
You must be signed in to change notification settings - Fork 0
/
flash.go
156 lines (128 loc) · 3.13 KB
/
flash.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
package model
import (
"context"
"fmt"
"time"
"github.com/rs/zerolog/log"
)
const (
// DefaultFlashDelay sets the flash clear delay.
DefaultFlashDelay = 3 * time.Second
// FlashInfo represents an info message.
FlashInfo FlashLevel = iota
// FlashWarn represents an warning message.
FlashWarn
// FlashErr represents an error message.
FlashErr
)
// LevelMessage tracks an message and severity.
type LevelMessage struct {
Level FlashLevel
Text string
}
func newClearMessage() LevelMessage {
return LevelMessage{}
}
// IsClear returns true if message is empty.
func (l LevelMessage) IsClear() bool {
return l.Text == ""
}
// FlashLevel represents flash message severity.
type FlashLevel int
// FlashChan represents a flash event channel.
type FlashChan chan LevelMessage
// FlashListener represents a text model listener.
type FlashListener interface {
// FlashChanged notifies the model changed.
FlashChanged(FlashLevel, string)
// FlashCleared notifies when the filter changed.
FlashCleared()
}
// Flash represents a flash message model.
type Flash struct {
msg LevelMessage
cancel context.CancelFunc
delay time.Duration
msgChan chan LevelMessage
}
// NewFlash returns a new instance.
func NewFlash(dur time.Duration) *Flash {
return &Flash{
delay: dur,
msgChan: make(FlashChan, 3),
}
}
// Channel returns the flash channel.
func (f *Flash) Channel() FlashChan {
return f.msgChan
}
// Info displays an info flash message.
func (f *Flash) Info(msg string) {
f.SetMessage(FlashInfo, msg)
}
// Infof displays a formatted info flash message.
func (f *Flash) Infof(fmat string, args ...interface{}) {
f.Info(fmt.Sprintf(fmat, args...))
}
// Warn displays a warning flash message.
func (f *Flash) Warn(msg string) {
log.Warn().Msg(msg)
f.SetMessage(FlashWarn, msg)
}
// Warnf displays a formatted warning flash message.
func (f *Flash) Warnf(fmat string, args ...interface{}) {
f.Warn(fmt.Sprintf(fmat, args...))
}
// Err displays an error flash message.
func (f *Flash) Err(err error) {
log.Error().Msg(err.Error())
f.SetMessage(FlashErr, err.Error())
}
// Errf displays a formatted error flash message.
func (f *Flash) 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...)
f.SetMessage(FlashErr, fmt.Sprintf(fmat, args...))
}
// Clear clears the flash message.
func (f *Flash) Clear() {
f.fireCleared()
}
// SetMessage sets the flash level message.
func (f *Flash) SetMessage(level FlashLevel, msg string) {
if f.cancel != nil {
f.cancel()
f.cancel = nil
}
f.setLevelMessage(LevelMessage{Level: level, Text: msg})
f.fireFlashChanged()
var ctx context.Context
ctx, f.cancel = context.WithCancel(context.Background())
go f.refresh(ctx)
}
func (f *Flash) refresh(ctx context.Context) {
for {
select {
case <-ctx.Done():
return
case <-time.After(f.delay):
f.fireCleared()
return
}
}
}
func (f *Flash) setLevelMessage(msg LevelMessage) {
f.msg = msg
}
func (f *Flash) fireFlashChanged() {
f.msgChan <- f.msg
}
func (f *Flash) fireCleared() {
f.msgChan <- newClearMessage()
}