ui.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. package ui
  2. import (
  3. "mimicry/pub"
  4. "mimicry/ansi"
  5. "mimicry/feed"
  6. "fmt"
  7. "log"
  8. )
  9. type State struct {
  10. /* the 0 index is special; it is rendered in full, not as a preview.
  11. the others are all rendered as previews. negative indexes represent
  12. parents of the 0th element (found via `inReplyTo`) and positive
  13. elements represent children (found via the pertinent collection,
  14. e.g. `replies` for a post or `outbox` for an actor) */
  15. feed *feed.Feed
  16. index int
  17. context int
  18. page pub.Container
  19. basepoint uint
  20. }
  21. func (s *State) View(width int, height uint) string {
  22. //return s.feed.Get(0).String(width)
  23. var top, center, bottom string
  24. //TODO: this should be bounded based on size of feed
  25. for i := s.index - s.context; i <= s.index + s.context; i++ {
  26. if !s.feed.Contains(i) {
  27. continue
  28. }
  29. var serialized string
  30. if i == 0 {
  31. serialized = s.feed.Get(i).String(width - 4)
  32. log.Printf("%d\n", len(serialized))
  33. } else if i > 0 {
  34. serialized = "╰ " + ansi.Indent(s.feed.Get(i).Preview(width - 4), " ", false)
  35. } else {
  36. serialized = s.feed.Get(i).Preview(width - 4)
  37. }
  38. if i == s.index {
  39. center = ansi.Indent(serialized, "┃ ", true)
  40. } else if i < s.index {
  41. if top != "" { top += "\n" }
  42. top += ansi.Indent(serialized + "\n│", " ", true)
  43. } else {
  44. if bottom != "" { bottom = "\n" + bottom }
  45. bottom = ansi.Indent("│\n" + serialized, " ", true) + bottom
  46. }
  47. }
  48. log.Printf("%s\n", center)
  49. return ansi.CenterVertically(top, center, bottom, height)
  50. }
  51. func (s *State) Update(input byte) {
  52. /* Interesting problem, but you will succeed! */
  53. switch input {
  54. case 'k': // up
  55. mayNeedLoading := s.index - 1 - s.context
  56. if !s.feed.Contains(mayNeedLoading) {
  57. if s.feed.Contains(mayNeedLoading - 1) {
  58. s.feed.Prepend(s.feed.Get(mayNeedLoading - 1).Parents(1))
  59. }
  60. }
  61. if s.feed.Contains(s.index - 1) {
  62. s.index -= 1
  63. }
  64. case 'j': // down
  65. mayNeedLoading := s.index + 1 + s.context
  66. if !s.feed.Contains(mayNeedLoading) {
  67. if s.page != nil {
  68. var children []pub.Tangible
  69. children, s.page, s.basepoint = s.page.Harvest(1, s.basepoint)
  70. s.feed.Append(children)
  71. }
  72. }
  73. if s.feed.Contains(s.index + 1) {
  74. s.index += 1
  75. }
  76. }
  77. // TODO: the catchall down here will be to look at s.feed.Get(s.index).References()
  78. // for urls to switch to
  79. }
  80. func (s *State) SwitchTo(item pub.Any) {
  81. switch narrowed := item.(type) {
  82. case pub.Tangible:
  83. s.feed = feed.Create(narrowed)
  84. s.feed.Prepend(narrowed.Parents(uint(s.context)))
  85. var children []pub.Tangible
  86. children, s.page, s.basepoint = narrowed.Children(uint(s.context))
  87. s.feed.Append(children)
  88. case pub.Container:
  89. var children []pub.Tangible
  90. children, s.page, s.basepoint = narrowed.Harvest(uint(s.context), 0)
  91. s.feed = feed.CreateAndAppend(children)
  92. default:
  93. panic(fmt.Sprintf("unrecognized non-Tangible non-Container: %T", item))
  94. }
  95. }
  96. func Start(input string) *State {
  97. item := pub.FetchUserInput(input)
  98. log.Printf("%v\n", item)
  99. s := &State{
  100. feed: &feed.Feed{},
  101. index: 0,
  102. context: 1,
  103. }
  104. s.SwitchTo(item)
  105. return s
  106. }