Files
moonmath/tui/tui.go
T

101 lines
2.3 KiB
Go
Raw Normal View History

2024-03-19 18:38:46 -07:00
package tui
import (
"fmt"
2024-03-22 17:43:15 -07:00
"code.humancabbage.net/sam/moonmath/coindesk"
2024-03-19 21:44:11 -07:00
"code.humancabbage.net/sam/moonmath/config"
2024-03-22 17:43:15 -07:00
"code.humancabbage.net/sam/moonmath/tui/asset"
2024-03-22 21:12:14 -07:00
"code.humancabbage.net/sam/moonmath/tui/perf"
2024-03-19 18:38:46 -07:00
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
)
2024-03-22 17:43:15 -07:00
type Model struct {
2024-03-22 21:12:14 -07:00
assets []asset.Model
stats perf.Model
displayStats bool
2024-03-22 17:43:15 -07:00
}
2024-03-22 21:12:14 -07:00
func New(assets []coindesk.Asset, cfg config.All, displayStats bool) (m Model) {
m.stats = perf.New()
m.displayStats = displayStats
2024-03-22 17:43:15 -07:00
// construct models for each asset, but don't filter out dupes
seen := map[coindesk.Asset]struct{}{}
for _, a := range assets {
_, ok := seen[a]
if ok {
continue
2024-03-21 02:28:56 -07:00
}
2024-03-22 17:43:15 -07:00
assetCfg := cfg.GetData(a)
assetModel := asset.New(assetCfg)
m.assets = append(m.assets, assetModel)
seen[a] = struct{}{}
2024-03-21 02:28:56 -07:00
}
return
2024-03-19 18:38:46 -07:00
}
func (m Model) Init() tea.Cmd {
2024-03-22 17:43:15 -07:00
// initialize child models, collecting their commands,
// then return them all in a batch
var inits []tea.Cmd
for i := range m.assets {
cmd := m.assets[i].Init()
inits = append(inits, cmd)
}
return tea.Batch(inits...)
2024-03-19 18:38:46 -07:00
}
func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
2024-03-22 21:12:14 -07:00
m.stats.AddUpdate()
2024-03-19 18:38:46 -07:00
switch msg := msg.(type) {
2024-03-22 17:43:15 -07:00
// handle keys for quitting
2024-03-19 18:38:46 -07:00
case tea.KeyMsg:
switch msg.String() {
case "ctrl+c", "q", "esc":
return m, tea.Quit
}
2024-03-22 17:43:15 -07:00
// forward asset messages to the appropriate model
case asset.Msg:
cmd := m.forward(msg.Asset, msg)
return m, cmd
// forward any other message to each child model.
// typically, this is for animation.
default:
var commands []tea.Cmd
for i := range m.assets {
var cmd tea.Cmd
m.assets[i], cmd = m.assets[i].Update(msg)
commands = append(commands, cmd)
}
return m, tea.Batch(commands...)
2024-03-19 18:38:46 -07:00
}
return m, nil
}
2024-03-22 17:43:15 -07:00
func (m Model) View() string {
2024-03-22 21:12:14 -07:00
m.stats.AddView()
2024-03-22 17:43:15 -07:00
var ss []string
for i := range m.assets {
s := m.assets[i].View()
ss = append(ss, s)
2024-03-20 23:40:38 -07:00
}
2024-03-22 21:12:14 -07:00
if m.displayStats {
ss = append(ss, m.stats.View())
}
2024-03-22 17:43:15 -07:00
r := lipgloss.JoinVertical(lipgloss.Center, ss...)
return r
2024-03-20 23:40:38 -07:00
}
2024-03-19 18:38:46 -07:00
2024-03-22 17:43:15 -07:00
func (m Model) forward(a coindesk.Asset, msg tea.Msg) (cmd tea.Cmd) {
// O(n) is fine when n is small
for i := range m.assets {
if !m.assets[i].Handles(a) {
continue
2024-03-19 18:38:46 -07:00
}
2024-03-22 17:43:15 -07:00
m.assets[i], cmd = m.assets[i].Update(msg)
return
2024-03-19 18:38:46 -07:00
}
2024-03-22 17:43:15 -07:00
panic(fmt.Errorf("rogue message: %v", msg))
2024-03-19 18:38:46 -07:00
}