1package tui
  2
  3import (
  4	"fmt"
  5
  6	tea "github.com/charmbracelet/bubbletea"
  7	"github.com/charmbracelet/lipgloss"
  8	"github.com/charmbracelet/soft/config"
  9	br "github.com/charmbracelet/soft/tui/bubbles/repo"
 10	"github.com/charmbracelet/soft/tui/bubbles/selection"
 11	"github.com/muesli/termenv"
 12)
 13
 14type errMsg struct{ err error }
 15
 16func (e errMsg) Error() string {
 17	return e.err.Error()
 18}
 19
 20func (b *Bubble) setupCmd() tea.Msg {
 21	if b.config == nil || b.config.Source == nil {
 22		return errMsg{err: fmt.Errorf("config not set")}
 23	}
 24	lipgloss.SetColorProfile(termenv.ANSI256)
 25	mes, err := b.menuEntriesFromSource()
 26	if err != nil {
 27		return errMsg{err}
 28	}
 29	if len(mes) == 0 {
 30		return errMsg{fmt.Errorf("no repos found")}
 31	}
 32	b.repoMenu = mes
 33	rs := make([]string, 0)
 34	for _, m := range mes {
 35		rs = append(rs, m.Name)
 36	}
 37	b.repoSelect = selection.NewBubble(rs, b.styles)
 38	b.boxes[0] = b.repoSelect
 39
 40	// Jump to an initial repo
 41	ir := -1
 42	if b.initialRepo != "" {
 43		for i, me := range b.repoMenu {
 44			if me.Repo == b.initialRepo {
 45				ir = i
 46			}
 47		}
 48	}
 49	if ir == -1 {
 50		b.boxes[1] = b.repoMenu[0].bubble
 51		b.activeBox = 0
 52	} else {
 53		b.boxes[1] = b.repoMenu[ir].bubble
 54		b.repoSelect.SelectedItem = ir
 55		b.activeBox = 1
 56	}
 57
 58	b.state = loadedState
 59	return nil
 60}
 61
 62func (b *Bubble) menuEntriesFromSource() ([]MenuEntry, error) {
 63	mes := make([]MenuEntry, 0)
 64	for _, r := range b.config.Repos {
 65		me, err := b.newMenuEntry(r.Name, r.Repo)
 66		if err != nil {
 67			return nil, err
 68		}
 69		mes = append(mes, me)
 70	}
 71	rs := b.config.Source.AllRepos()
 72OUTER:
 73	for _, r := range rs {
 74		for _, me := range mes {
 75			if r.Name == me.Repo {
 76				continue OUTER
 77			}
 78		}
 79		me, err := b.newMenuEntry(r.Name, r.Name)
 80		if err != nil {
 81			return nil, err
 82		}
 83		mes = append(mes, me)
 84	}
 85	return mes, nil
 86}
 87
 88func (b *Bubble) newMenuEntry(name string, repo string) (MenuEntry, error) {
 89	var tmplConfig *config.Config
 90	me := MenuEntry{Name: name, Repo: repo}
 91	width := b.width
 92	boxLeftWidth := b.styles.Menu.GetWidth() + b.styles.Menu.GetHorizontalFrameSize()
 93	// TODO: also send this along with a tea.WindowSizeMsg
 94	var heightMargin = lipgloss.Height(b.headerView()) +
 95		lipgloss.Height(b.footerView()) +
 96		b.styles.RepoBody.GetVerticalFrameSize() +
 97		b.styles.App.GetVerticalMargins()
 98	if repo == "config" {
 99		tmplConfig = b.config
100	}
101	rb := br.NewBubble(
102		b.config.Source,
103		me.Repo,
104		b.styles,
105		width,
106		boxLeftWidth,
107		b.height,
108		heightMargin,
109		tmplConfig,
110	)
111	rb.Host = b.config.Host
112	rb.Port = b.config.Port
113	initCmd := rb.Init()
114	msg := initCmd()
115	switch msg := msg.(type) {
116	case br.ErrMsg:
117		return me, fmt.Errorf("missing %s: %s", me.Repo, msg.Error)
118	}
119	me.bubble = rb
120	return me, nil
121}