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}