tui.go 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. package tui
  2. import (
  3. "fmt"
  4. "github.com/NimbleMarkets/ntcharts/linechart/streamlinechart"
  5. tea "github.com/charmbracelet/bubbletea"
  6. "github.com/charmbracelet/lipgloss"
  7. )
  8. // Bubbletea model
  9. //
  10. // BUG(state): how do declare pointer here?
  11. type Model struct {
  12. width int
  13. Addresses []Address // as defined in internal/tui/types.go
  14. }
  15. func InitialModel(addresses []string) Model {
  16. var model Model
  17. for _, address := range addresses {
  18. var addr Address
  19. addr.max_results = 10
  20. addr.Address = address
  21. model.Addresses = append(model.Addresses, addr)
  22. }
  23. return model
  24. }
  25. func (m Model) Init() tea.Cmd {
  26. return m.Poll
  27. }
  28. func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
  29. switch msg := msg.(type) {
  30. // if case is KeyMsg (keypress)
  31. case tea.WindowSizeMsg:
  32. m.width = msg.Width
  33. for i, address := range m.Addresses {
  34. address.max_results = m.width
  35. m.Addresses[i] = address
  36. }
  37. case tea.KeyMsg:
  38. return m, tea.Quit
  39. case pollMsg:
  40. m.Poll()
  41. }
  42. return m, m.Poll
  43. }
  44. func (m Model) View() string {
  45. var headerStyle = lipgloss.NewStyle().
  46. Bold(true).
  47. Italic(true)
  48. var blockStyle = lipgloss.NewStyle().
  49. Width(m.width).
  50. Align(lipgloss.Center)
  51. output := "Results:\n\n"
  52. for _, address := range m.Addresses {
  53. if len(address.results) == 0 {
  54. output = output + fmt.Sprintf("%s\tloading...\n\n", headerStyle.Render(address.Address))
  55. } else {
  56. output = output + fmt.Sprintf("%s\n\n", blockStyle.Render(headerStyle.Render(address.Address)))
  57. // Linechart
  58. slc := streamlinechart.New(m.width, 10)
  59. for _, v := range address.results {
  60. slc.Push(v)
  61. }
  62. slc.Draw()
  63. output = output + fmt.Sprintf("%s\n\n", slc.View())
  64. }
  65. }
  66. return output
  67. }
  68. // A wrapper for the underlying [tui.Address.Poll] function. For each address in
  69. // [tui.Model.Addresses], run its respective Poll function and update [tui.Model]
  70. //
  71. // NOTE(async): this function fully blocks execution of the current thread.
  72. func (m Model) Poll() tea.Msg {
  73. for i, element := range m.Addresses {
  74. element.Poll()
  75. m.Addresses[i] = element
  76. }
  77. return true
  78. }