| 
									
										
										
										
											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
										 |  |  | } |