sointu/tracker/alert.go
2024-10-15 09:09:17 +03:00

113 lines
2.2 KiB
Go

package tracker
import (
"container/heap"
"time"
)
const alertSpeed = 10 // units: fadeLevels per second
const defaultAlertDuration = time.Second * 3
type (
Alert struct {
Name string
Priority AlertPriority
Message string
Duration time.Duration
FadeLevel float64
}
AlertPriority int
AlertYieldFunc func(index int, alert Alert) bool
Alerts Model
)
const (
None AlertPriority = iota
Info
Warning
Error
)
// Model methods
func (m *Model) Alerts() *Alerts { return (*Alerts)(m) }
// Alerts methods
func (m *Alerts) Iterate(yield func(index int, alert Alert) bool) {
for i, a := range m.alerts {
if !yield(i, a) {
break
}
}
}
func (m *Alerts) Update(d time.Duration) (animating bool) {
for i := len(m.alerts) - 1; i >= 0; i-- {
if m.alerts[i].Duration >= d {
m.alerts[i].Duration -= d
if m.alerts[i].FadeLevel < 1 {
animating = true
m.alerts[i].FadeLevel += float64(alertSpeed*d) / float64(time.Second)
if m.alerts[i].FadeLevel > 1 {
m.alerts[i].FadeLevel = 1
}
}
} else {
m.alerts[i].Duration = 0
m.alerts[i].FadeLevel -= float64(alertSpeed*d) / float64(time.Second)
animating = true
if m.alerts[i].FadeLevel < 0 {
heap.Remove(m, i)
}
}
}
return
}
func (m *Alerts) Add(message string, priority AlertPriority) {
m.AddAlert(Alert{
Priority: priority,
Message: message,
Duration: defaultAlertDuration,
})
}
func (m *Alerts) AddNamed(name, message string, priority AlertPriority) {
m.AddAlert(Alert{
Name: name,
Priority: priority,
Message: message,
Duration: defaultAlertDuration,
})
}
func (m *Alerts) AddAlert(a Alert) {
for i := range m.alerts {
if n := m.alerts[i].Name; n != "" && n == a.Name {
a.FadeLevel = m.alerts[i].FadeLevel
m.alerts[i] = a
heap.Fix(m, i)
return
}
}
heap.Push(m, a)
}
func (m *Alerts) Push(x any) {
m.alerts = append(m.alerts, x.(Alert))
}
func (m *Alerts) Pop() any {
old := m.alerts
n := len(old)
x := old[n-1]
m.alerts = old[0 : n-1]
return x
}
func (m Alerts) Len() int { return len(m.alerts) }
func (m Alerts) Less(i, j int) bool { return m.alerts[i].Priority < m.alerts[j].Priority }
func (m Alerts) Swap(i, j int) { m.alerts[i], m.alerts[j] = m.alerts[j], m.alerts[i] }