Sam Fredrickson
270534c0d5
All checks were successful
Build & Test / Main (push) Successful in 59s
Also, add a quick-and-dirty model for displaying basic performance stats, currently just the number of calls to the root Update() and View() methods.
101 lines
2.3 KiB
Go
101 lines
2.3 KiB
Go
package tui
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"code.humancabbage.net/sam/moonmath/coindesk"
|
|
"code.humancabbage.net/sam/moonmath/config"
|
|
"code.humancabbage.net/sam/moonmath/tui/asset"
|
|
"code.humancabbage.net/sam/moonmath/tui/perf"
|
|
tea "github.com/charmbracelet/bubbletea"
|
|
"github.com/charmbracelet/lipgloss"
|
|
)
|
|
|
|
type Model struct {
|
|
assets []asset.Model
|
|
stats perf.Model
|
|
displayStats bool
|
|
}
|
|
|
|
func New(assets []coindesk.Asset, cfg config.All, displayStats bool) (m Model) {
|
|
m.stats = perf.New()
|
|
m.displayStats = displayStats
|
|
// 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
|
|
}
|
|
assetCfg := cfg.GetData(a)
|
|
assetModel := asset.New(assetCfg)
|
|
m.assets = append(m.assets, assetModel)
|
|
seen[a] = struct{}{}
|
|
}
|
|
return
|
|
}
|
|
|
|
func (m Model) Init() tea.Cmd {
|
|
// 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...)
|
|
}
|
|
|
|
func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|
m.stats.AddUpdate()
|
|
switch msg := msg.(type) {
|
|
// handle keys for quitting
|
|
case tea.KeyMsg:
|
|
switch msg.String() {
|
|
case "ctrl+c", "q", "esc":
|
|
return m, tea.Quit
|
|
}
|
|
// 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...)
|
|
}
|
|
return m, nil
|
|
}
|
|
|
|
func (m Model) View() string {
|
|
m.stats.AddView()
|
|
var ss []string
|
|
for i := range m.assets {
|
|
s := m.assets[i].View()
|
|
ss = append(ss, s)
|
|
}
|
|
if m.displayStats {
|
|
ss = append(ss, m.stats.View())
|
|
}
|
|
r := lipgloss.JoinVertical(lipgloss.Center, ss...)
|
|
return r
|
|
}
|
|
|
|
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
|
|
}
|
|
m.assets[i], cmd = m.assets[i].Update(msg)
|
|
return
|
|
}
|
|
panic(fmt.Errorf("rogue message: %v", msg))
|
|
}
|