123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137 |
- package ui
- import (
- "mimicry/pub"
- "mimicry/ansi"
- "mimicry/feed"
- "fmt"
- "sync"
- )
- type State struct {
-
- feed *feed.Feed
- index int
- context int
- page pub.Container
- basepoint uint
- }
- func (s *State) View(width int, height uint) string {
-
- var top, center, bottom string
-
- for i := s.index - s.context; i <= s.index + s.context; i++ {
- if !s.feed.Contains(i) {
- continue
- }
- var serialized string
- if i == 0 {
- serialized = s.feed.Get(i).String(width - 4)
- } else if i > 0 {
- serialized = "╰ " + ansi.Indent(s.feed.Get(i).Preview(width - 4), " ", false)
- } else {
- serialized = s.feed.Get(i).Preview(width - 4)
- }
- if i == s.index {
- center = ansi.Indent(serialized, "┃ ", true)
- } else if i < s.index {
- if top != "" { top += "\n" }
- top += ansi.Indent(serialized + "\n│", " ", true)
- } else {
- if bottom != "" { bottom += "\n" }
- bottom += ansi.Indent("│\n" + serialized, " ", true)
- }
- }
- return ansi.CenterVertically(top, center, bottom, height)
- }
- func (s *State) Update(input byte) {
-
- switch input {
- case 'k':
- mayNeedLoading := s.index - s.context - 1
- if !s.feed.Contains(mayNeedLoading) {
- if s.feed.Contains(mayNeedLoading + 1) {
- s.feed.Prepend(s.feed.Get(mayNeedLoading + 1).Parents(1))
- }
- }
- if s.feed.Contains(s.index - 1) {
- s.index -= 1
-
- s.PreloadUp(s.context)
- }
- case 'j':
- mayNeedLoading := s.index + 1 + s.context
- if !s.feed.Contains(mayNeedLoading) {
- if s.page != nil {
- var children []pub.Tangible
- children, s.page, s.basepoint = s.page.Harvest(1, s.basepoint)
- s.feed.Append(children)
- }
- }
- if s.feed.Contains(s.index + 1) {
- s.index += 1
-
- s.PreloadDown(s.context)
- }
- }
-
-
- }
- func (s *State) SwitchTo(item pub.Any) {
- switch narrowed := item.(type) {
- case pub.Tangible:
- s.feed = feed.Create(narrowed)
- var parents, children []pub.Tangible
- var wg sync.WaitGroup
- wg.Add(2)
- go func() {parents = narrowed.Parents(uint(s.context)); wg.Done()}()
- go func() {children, s.page, s.basepoint = narrowed.Children(uint(s.context)); wg.Done()}()
- wg.Wait()
- s.feed.Prepend(parents)
- s.feed.Append(children)
- s.PreloadUp(s.context)
- s.PreloadDown(s.context)
- case pub.Container:
- var children []pub.Tangible
- children, s.page, s.basepoint = narrowed.Harvest(uint(s.context), 0)
- s.feed = feed.CreateAndAppend(children)
- s.PreloadDown(s.context)
- default:
- panic(fmt.Sprintf("unrecognized non-Tangible non-Container: %T", item))
- }
- }
- func (s *State) PreloadDown(amount int) {
- if s.page != nil {
- go s.page.Harvest(uint(amount), s.basepoint)
- }
- }
- func (s *State) PreloadUp(amount int) {
- if s.feed.Contains(s.index - s.context) {
- go s.feed.Get(s.index - s.context).Parents(uint(amount))
- }
- }
- func Start(input string) *State {
- item := pub.FetchUserInput(input)
- s := &State{
- feed: &feed.Feed{},
- index: 0,
- context: 5,
- }
- s.SwitchTo(item)
- return s
- }
|