repo.go

  1package repo
  2
  3import (
  4	"github.com/charmbracelet/bubbles/key"
  5	tea "github.com/charmbracelet/bubbletea"
  6	"github.com/charmbracelet/lipgloss"
  7	ggit "github.com/charmbracelet/soft-serve/git"
  8	"github.com/charmbracelet/soft-serve/ui/common"
  9	"github.com/charmbracelet/soft-serve/ui/components/code"
 10	"github.com/charmbracelet/soft-serve/ui/components/selector"
 11	"github.com/charmbracelet/soft-serve/ui/components/statusbar"
 12	"github.com/charmbracelet/soft-serve/ui/components/tabs"
 13	"github.com/charmbracelet/soft-serve/ui/git"
 14)
 15
 16type tab int
 17
 18const (
 19	readmeTab tab = iota
 20	filesTab
 21	commitsTab
 22	branchesTab
 23	tagsTab
 24)
 25
 26type RepoMsg git.GitRepo
 27
 28type Repo struct {
 29	common       common.Common
 30	rs           git.GitRepoSource
 31	selectedRepo git.GitRepo
 32	activeTab    tab
 33	tabs         *tabs.Tabs
 34	statusbar    *statusbar.StatusBar
 35	readme       *code.Code
 36	log          *Log
 37	ref          *ggit.Reference
 38}
 39
 40func New(common common.Common, rs git.GitRepoSource) *Repo {
 41	sb := statusbar.New(common)
 42	tb := tabs.New(common, []string{"Readme", "Files", "Commits", "Branches", "Tags"})
 43	readme := code.New(common, "", "")
 44	readme.NoContentStyle = readme.NoContentStyle.SetString("No readme found.")
 45	r := &Repo{
 46		common:    common,
 47		rs:        rs,
 48		tabs:      tb,
 49		statusbar: sb,
 50		readme:    readme,
 51	}
 52	return r
 53}
 54
 55func (r *Repo) SetSize(width, height int) {
 56	r.common.SetSize(width, height)
 57	hm := 4
 58	r.tabs.SetSize(width, height-hm)
 59	r.statusbar.SetSize(width, height-hm)
 60	r.readme.SetSize(width, height-hm)
 61	if r.log != nil {
 62		r.log.SetSize(width, height-hm)
 63	}
 64}
 65
 66func (r *Repo) ShortHelp() []key.Binding {
 67	b := make([]key.Binding, 0)
 68	tab := r.common.Keymap.Section
 69	tab.SetHelp("tab", "switch tab")
 70	b = append(b, r.common.Keymap.Back)
 71	b = append(b, tab)
 72	return b
 73}
 74
 75func (r *Repo) FullHelp() [][]key.Binding {
 76	b := make([][]key.Binding, 0)
 77	return b
 78}
 79
 80func (r *Repo) Init() tea.Cmd {
 81	return nil
 82}
 83
 84func (r *Repo) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
 85	cmds := make([]tea.Cmd, 0)
 86	switch msg := msg.(type) {
 87	case selector.SelectMsg:
 88		r.activeTab = 0
 89		cmds = append(cmds, r.tabs.Init(), r.setRepoCmd(string(msg)))
 90	case RepoMsg:
 91		r.selectedRepo = git.GitRepo(msg)
 92		cmds = append(cmds, r.updateStatusBarCmd, r.updateReadmeCmd)
 93	case tabs.ActiveTabMsg:
 94		r.activeTab = tab(msg)
 95	}
 96	t, cmd := r.tabs.Update(msg)
 97	r.tabs = t.(*tabs.Tabs)
 98	if cmd != nil {
 99		cmds = append(cmds, cmd)
100	}
101	s, cmd := r.statusbar.Update(msg)
102	r.statusbar = s.(*statusbar.StatusBar)
103	if cmd != nil {
104		cmds = append(cmds, cmd)
105	}
106	switch r.activeTab {
107	case readmeTab:
108		b, cmd := r.readme.Update(msg)
109		r.readme = b.(*code.Code)
110		if cmd != nil {
111			cmds = append(cmds, cmd)
112		}
113	case filesTab:
114	case commitsTab:
115		if r.log == nil {
116			r.log = NewLog(r.common)
117			cmds = append(cmds, r.log.Init())
118		}
119		l, cmd := r.log.Update(msg)
120		r.log = l.(*Log)
121		if cmd != nil {
122			cmds = append(cmds, cmd)
123		}
124	case branchesTab:
125	case tagsTab:
126	}
127	return r, tea.Batch(cmds...)
128}
129
130func (r *Repo) View() string {
131	s := r.common.Styles.RepoBody.Copy().
132		Width(r.common.Width).
133		Height(r.common.Height)
134	mainStyle := lipgloss.NewStyle().
135		Height(r.common.Height-4).
136		Margin(1, 0)
137	main := mainStyle.Render("")
138	switch r.activeTab {
139	case readmeTab:
140		main = mainStyle.Render(r.readme.View())
141	case filesTab:
142	case commitsTab:
143		if r.log != nil {
144			main = mainStyle.Render(r.log.View())
145		}
146	}
147	view := lipgloss.JoinVertical(lipgloss.Top,
148		r.tabs.View(),
149		main,
150		r.statusbar.View(),
151	)
152	return s.Render(view)
153}
154
155func (r *Repo) setRepoCmd(repo string) tea.Cmd {
156	return func() tea.Msg {
157		for _, r := range r.rs.AllRepos() {
158			if r.Name() == repo {
159				return RepoMsg(r)
160			}
161		}
162		return common.ErrorMsg(git.ErrMissingRepo)
163	}
164}
165
166func (r *Repo) updateStatusBarCmd() tea.Msg {
167	branch, err := r.selectedRepo.HEAD()
168	if err != nil {
169		return common.ErrorMsg(err)
170	}
171	return statusbar.StatusBarMsg{
172		Key:    r.selectedRepo.Name(),
173		Value:  "",
174		Info:   "",
175		Branch: branch.Name().Short(),
176	}
177}
178
179func (r *Repo) updateReadmeCmd() tea.Msg {
180	if r.selectedRepo == nil {
181		return common.ErrorCmd(git.ErrMissingRepo)
182	}
183	rm, rp := r.selectedRepo.Readme()
184	return r.readme.SetContent(rm, rp)
185}