refs.go

  1package repo
  2
  3import (
  4	"sort"
  5	"strings"
  6
  7	tea "github.com/charmbracelet/bubbletea"
  8	ggit "github.com/charmbracelet/soft-serve/git"
  9	"github.com/charmbracelet/soft-serve/ui/common"
 10	"github.com/charmbracelet/soft-serve/ui/components/selector"
 11	"github.com/charmbracelet/soft-serve/ui/components/tabs"
 12	"github.com/charmbracelet/soft-serve/ui/git"
 13)
 14
 15type RefItemsMsg struct {
 16	prefix string
 17	items  []selector.IdentifiableItem
 18}
 19
 20type Refs struct {
 21	common    common.Common
 22	selector  *selector.Selector
 23	repo      git.GitRepo
 24	ref       *ggit.Reference
 25	activeRef *ggit.Reference
 26	refPrefix string
 27}
 28
 29func NewRefs(common common.Common, refPrefix string) *Refs {
 30	r := &Refs{
 31		common:    common,
 32		refPrefix: refPrefix,
 33	}
 34	s := selector.New(common, []selector.IdentifiableItem{}, RefItemDelegate{common.Styles})
 35	s.SetShowFilter(false)
 36	s.SetShowHelp(false)
 37	s.SetShowPagination(true)
 38	s.SetShowStatusBar(false)
 39	s.SetShowTitle(false)
 40	s.SetFilteringEnabled(false)
 41	s.DisableQuitKeybindings()
 42	r.selector = s
 43	return r
 44}
 45
 46func (r *Refs) SetSize(width, height int) {
 47	r.common.SetSize(width, height)
 48	r.selector.SetSize(width, height)
 49}
 50
 51func (r *Refs) Init() tea.Cmd {
 52	return r.updateItemsCmd
 53}
 54
 55func (r *Refs) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
 56	cmds := make([]tea.Cmd, 0)
 57	switch msg := msg.(type) {
 58	case RepoMsg:
 59		r.selector.Select(0)
 60		r.repo = git.GitRepo(msg)
 61		cmds = append(cmds, r.Init())
 62	case RefMsg:
 63		r.ref = msg
 64		cmds = append(cmds, r.Init())
 65	case RefItemsMsg:
 66		cmds = append(cmds, r.selector.SetItems(msg.items))
 67		r.activeRef = r.selector.SelectedItem().(RefItem).Reference
 68	case selector.ActiveMsg:
 69		switch sel := msg.IdentifiableItem.(type) {
 70		case RefItem:
 71			r.activeRef = sel.Reference
 72		}
 73		cmds = append(cmds, updateStatusBarCmd)
 74	case selector.SelectMsg:
 75		switch i := msg.IdentifiableItem.(type) {
 76		case RefItem:
 77			cmds = append(cmds,
 78				switchRefCmd(i.Reference),
 79				tabs.SelectTabCmd(int(filesTab)),
 80			)
 81		}
 82	case tea.KeyMsg:
 83		switch msg.String() {
 84		case "l", "right":
 85			cmds = append(cmds, r.selector.SelectItem)
 86		}
 87	}
 88	m, cmd := r.selector.Update(msg)
 89	r.selector = m.(*selector.Selector)
 90	if cmd != nil {
 91		cmds = append(cmds, cmd)
 92	}
 93	return r, tea.Batch(cmds...)
 94}
 95
 96func (r *Refs) View() string {
 97	return r.selector.View()
 98}
 99
100func (r *Refs) StatusBarValue() string {
101	if r.activeRef == nil {
102		return ""
103	}
104	return r.activeRef.Name().String()
105}
106
107func (r *Refs) StatusBarInfo() string {
108	return ""
109}
110
111func (r *Refs) updateItemsCmd() tea.Msg {
112	its := make(RefItems, 0)
113	refs, err := r.repo.References()
114	if err != nil {
115		return common.ErrorMsg(err)
116	}
117	for _, ref := range refs {
118		if strings.HasPrefix(ref.Name().String(), r.refPrefix) {
119			its = append(its, RefItem{ref})
120		}
121	}
122	sort.Sort(its)
123	items := make([]selector.IdentifiableItem, len(its))
124	for i, it := range its {
125		items[i] = it
126	}
127	return RefItemsMsg{
128		items:  items,
129		prefix: r.refPrefix,
130	}
131}
132
133func switchRefCmd(ref *ggit.Reference) tea.Cmd {
134	return func() tea.Msg {
135		return RefMsg(ref)
136	}
137}