Files
zeekayandHanzo Dev d9d3fe1566 Go 1.27.1, and the code it can say more simply
Modules declare go 1.27.1 and the build images follow. go fix applied the
modernizers, and the ptr helper went once new(expr) could say it; omitzero
is not applied, since it changes what the JSON says.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-16 19:34:14 -07:00

174 lines
4.5 KiB
Go

package views
import (
"fmt"
"strings"
"github.com/charmbracelet/lipgloss"
)
type ConnectionState int
const (
StateConnected ConnectionState = iota
StateDisconnected
StateReconnecting
StateAuthenticating
)
type StatusBarView struct {
connState ConnectionState
teamName string
paused bool
width int
viewMode string
eventTypeFilter string
distinctIDFilter string
}
func NewStatusBarView() *StatusBarView {
return &StatusBarView{
connState: StateDisconnected,
}
}
func (v *StatusBarView) SetSize(w int) {
v.width = w
}
func (v *StatusBarView) SetState(state ConnectionState) {
v.connState = state
}
func (v *StatusBarView) SetTeamName(name string) {
v.teamName = name
}
func (v *StatusBarView) SetPaused(p bool) {
v.paused = p
}
func (v *StatusBarView) SetViewMode(mode string) {
v.viewMode = mode
}
func (v *StatusBarView) SetFilters(eventType, distinctID string) {
v.eventTypeFilter = eventType
v.distinctIDFilter = distinctID
}
func (v *StatusBarView) ViewHeader() string {
headerStyle := lipgloss.NewStyle().
Bold(true).
Foreground(lipgloss.Color("#FFFFFF")).
Background(lipgloss.Color("#333333")).
Padding(0, 1)
connectedStyle := lipgloss.NewStyle().Foreground(lipgloss.AdaptiveColor{Light: "#388E3C", Dark: "#77B96C"}).Bold(true)
disconnectedStyle := lipgloss.NewStyle().Foreground(lipgloss.AdaptiveColor{Light: "#D32F2F", Dark: "#EF5350"}).Bold(true)
reconnectingStyle := lipgloss.NewStyle().Foreground(lipgloss.AdaptiveColor{Light: "#F57C00", Dark: "#FFB74D"}).Bold(true)
pausedStyle := lipgloss.NewStyle().Foreground(lipgloss.AdaptiveColor{Light: "#F57C00", Dark: "#FFB74D"}).Bold(true)
logoColors := []lipgloss.Color{"#CCCCCC", "#8F8F8F", "#333333", "#1D1F27"}
var logo strings.Builder
for _, c := range logoColors {
logo.WriteString(lipgloss.NewStyle().Background(c).Render(" "))
}
title := headerStyle.Render(" Insights Live ") + " " + logo.String()
var state string
switch v.connState {
case StateConnected:
state = connectedStyle.Render("Connected")
case StateDisconnected:
state = disconnectedStyle.Render("Disconnected")
case StateReconnecting:
state = reconnectingStyle.Render("Reconnecting...")
case StateAuthenticating:
state = reconnectingStyle.Render("Authenticating...")
}
if v.paused {
state += " " + pausedStyle.Render("[PAUSED]")
}
filterStyle := lipgloss.NewStyle().
Foreground(lipgloss.AdaptiveColor{Light: "#333333", Dark: "#CCCCCC"})
filterLabelStyle := lipgloss.NewStyle().
Foreground(lipgloss.AdaptiveColor{Light: "#888888", Dark: "#666666"})
hintStyle := lipgloss.NewStyle().
Foreground(lipgloss.AdaptiveColor{Light: "#AAAAAA", Dark: "#555555"})
filters := ""
if v.eventTypeFilter != "" {
filters += " " + filterLabelStyle.Render("event:") + filterStyle.Render(v.eventTypeFilter) + hintStyle.Render(" [f]")
}
if v.distinctIDFilter != "" {
filters += " " + filterLabelStyle.Render("id:") + filterStyle.Render(v.distinctIDFilter) + hintStyle.Render(" [d]")
}
team := ""
if v.teamName != "" {
team = lipgloss.NewStyle().
Foreground(lipgloss.AdaptiveColor{Light: "#888888", Dark: "#666666"}).
Render(fmt.Sprintf("Team: %s", v.teamName))
}
// Right-align team name
gap := max(v.width-lipgloss.Width(title)-lipgloss.Width(state)-lipgloss.Width(filters)-lipgloss.Width(team)-4, 1)
spaces := lipgloss.NewStyle().Width(gap).Render("")
return title + " " + state + filters + spaces + team
}
func (v *StatusBarView) ViewFooter() string {
keyStyle := lipgloss.NewStyle().
Foreground(lipgloss.AdaptiveColor{Light: "#333333", Dark: "#CCCCCC"}).
Bold(true)
descStyle := lipgloss.NewStyle().
Foreground(lipgloss.AdaptiveColor{Light: "#888888", Dark: "#666666"})
footerStyle := lipgloss.NewStyle().
Padding(0, 1).
Width(v.width)
var bindings []struct{ key, desc string }
switch v.viewMode {
case "detail":
bindings = []struct{ key, desc string }{
{"esc", "back"},
{"j/k", "scroll"},
{"q", "quit"},
}
default:
bindings = []struct{ key, desc string }{
{"p", "pause"},
{"f", "filter event"},
{"d", "distinct ID"},
{"c", "columns"},
{"?", "help"},
{"enter", "detail"},
{"x", "clear"},
{"q", "quit"},
}
}
var parts []string
for _, b := range bindings {
parts = append(parts, keyStyle.Render("["+b.key+"]")+" "+descStyle.Render(b.desc))
}
var content strings.Builder
for i, p := range parts {
if i > 0 {
content.WriteString(descStyle.Render(" • "))
}
content.WriteString(p)
}
return footerStyle.Render(content.String())
}