fix(ui): populate about readme from config repo

Ayman Bagabas created

Change summary

proto/repo.go                   |  6 ++++++
ui/components/code/code.go      |  2 +-
ui/git/git.go                   |  2 +-
ui/pages/selection/item.go      | 18 ++++++++----------
ui/pages/selection/selection.go | 31 +++++++++++++++++++++----------
ui/styles/styles.go             |  6 +++---
6 files changed, 40 insertions(+), 25 deletions(-)

Detailed changes

proto/repo.go 🔗

@@ -55,3 +55,9 @@ func LatestFile(r Repository, pattern string) (string, string, error) {
 	}
 	return "", "", git.ErrFileNotFound
 }
+
+// Readme returns the repository's README.
+func Readme(r Repository) (readme string, path string, err error) {
+	readme, path, err = LatestFile(r, "README*")
+	return
+}

ui/components/code/code.go 🔗

@@ -47,7 +47,7 @@ func New(c common.Common, content, extension string) *Code {
 		content:        content,
 		extension:      extension,
 		Viewport:       vp.New(c),
-		NoContentStyle: c.Styles.CodeNoContent.Copy(),
+		NoContentStyle: c.Styles.NoContent.Copy(),
 		LineDigitStyle: lineDigitStyle,
 		LineBarStyle:   lineBarStyle,
 	}

ui/git/git.go 🔗

@@ -18,7 +18,7 @@ type Repository struct {
 
 // Readme returns the repository's README.
 func (r *Repository) Readme() (readme string, path string) {
-	readme, path, _ = r.LatestFile("README*")
+	readme, path, _ = proto.Readme(r.Repo)
 	return
 }
 

ui/pages/selection/item.go 🔗

@@ -38,7 +38,7 @@ func (it Items) Less(i int, j int) bool {
 		return true
 	}
 	if it[i].lastUpdate == nil && it[j].lastUpdate == nil {
-		return it[i].info.Name() < it[j].info.Name()
+		return it[i].repo.Info.Name() < it[j].repo.Info.Name()
 	}
 	return it[i].lastUpdate.After(*it[j].lastUpdate)
 }
@@ -50,8 +50,7 @@ func (it Items) Swap(i int, j int) {
 
 // Item represents a single item in the selector.
 type Item struct {
-	repo       proto.Repository
-	info       proto.Metadata
+	repo       git.Repository
 	lastUpdate *time.Time
 	cmd        string
 	copied     time.Time
@@ -70,8 +69,7 @@ func NewItem(info proto.Metadata, cfg *config.Config) (Item, error) {
 		lastUpdate = &lu
 	}
 	return Item{
-		repo:       repo,
-		info:       info,
+		repo:       git.Repository{repo, info},
 		lastUpdate: lastUpdate,
 		cmd:        git.RepoURL(cfg.Host, cfg.SSH.Port, info.Name()),
 	}, nil
@@ -79,19 +77,19 @@ func NewItem(info proto.Metadata, cfg *config.Config) (Item, error) {
 
 // ID implements selector.IdentifiableItem.
 func (i Item) ID() string {
-	return i.info.Name()
+	return i.repo.Info.Name()
 }
 
 // Title returns the item title. Implements list.DefaultItem.
 func (i Item) Title() string {
-	if pn := i.info.ProjectName(); pn != "" {
+	if pn := i.repo.Info.ProjectName(); pn != "" {
 		return pn
 	}
-	return i.info.Name()
+	return i.repo.Info.Name()
 }
 
 // Description returns the item description. Implements list.DefaultItem.
-func (i Item) Description() string { return i.info.Description() }
+func (i Item) Description() string { return i.repo.Info.Description() }
 
 // FilterValue implements list.Item.
 func (i Item) FilterValue() string { return i.Title() }
@@ -160,7 +158,7 @@ func (d ItemDelegate) Render(w io.Writer, m list.Model, index int, listItem list
 
 	title := i.Title()
 	title = common.TruncateString(title, m.Width()-styles.Base.GetHorizontalFrameSize())
-	if i.info.IsPrivate() {
+	if i.repo.Info.IsPrivate() {
 		title += " 🔒"
 	}
 	if isSelected {

ui/pages/selection/selection.go 🔗

@@ -4,6 +4,7 @@ import (
 	"fmt"
 	"log"
 	"sort"
+	"strings"
 
 	"github.com/charmbracelet/bubbles/key"
 	"github.com/charmbracelet/bubbles/list"
@@ -42,27 +43,27 @@ type Selection struct {
 }
 
 // New creates a new selection model.
-func New(common common.Common) *Selection {
+func New(c common.Common) *Selection {
 	ts := make([]string, lastPane)
 	for i, b := range []pane{selectorPane, readmePane} {
 		ts[i] = b.String()
 	}
-	t := tabs.New(common, ts)
+	t := tabs.New(c, ts)
 	t.TabSeparator = lipgloss.NewStyle()
-	t.TabInactive = common.Styles.TopLevelNormalTab.Copy()
-	t.TabActive = common.Styles.TopLevelActiveTab.Copy()
-	t.TabDot = common.Styles.TopLevelActiveTabDot.Copy()
+	t.TabInactive = c.Styles.TopLevelNormalTab.Copy()
+	t.TabActive = c.Styles.TopLevelActiveTab.Copy()
+	t.TabDot = c.Styles.TopLevelActiveTabDot.Copy()
 	t.UseDot = true
 	sel := &Selection{
-		common:     common,
+		common:     c,
 		activePane: selectorPane, // start with the selector focused
 		tabs:       t,
 	}
-	readme := code.New(common, "", "")
-	readme.NoContentStyle = readme.NoContentStyle.SetString("No readme found.")
-	selector := selector.New(common,
+	readme := code.New(c, "", "")
+	readme.NoContentStyle = c.Styles.NoContent.Copy().SetString("No readme found.")
+	selector := selector.New(c,
 		[]selector.IdentifiableItem{},
-		ItemDelegate{&common, &sel.activePane})
+		ItemDelegate{&c, &sel.activePane})
 	selector.SetShowTitle(false)
 	selector.SetShowHelp(false)
 	selector.SetShowStatusBar(false)
@@ -191,6 +192,16 @@ func (s *Selection) Init() tea.Cmd {
 	// Put configured repos first
 	for _, r := range repos {
 		log.Printf("adding configured repo %s", r.Name())
+		if r.Name() == "config" {
+			repo, err := r.Open()
+			if err != nil {
+				log.Printf("failed to open config repo: %v", err)
+				continue
+			}
+			rm, rp, _ := proto.Readme(repo)
+			s.readmeHeight = strings.Count(rm, "\n")
+			readmeCmd = s.readme.SetContent(rm, rp)
+		}
 		acc := cfg.AuthRepo(r.Name(), pk)
 		if r.IsPrivate() && acc < proto.ReadOnlyAccess {
 			continue

ui/styles/styles.go 🔗

@@ -124,7 +124,7 @@ type Styles struct {
 	Spinner          lipgloss.Style
 	SpinnerContainer lipgloss.Style
 
-	CodeNoContent lipgloss.Style
+	NoContent lipgloss.Style
 
 	NoItems lipgloss.Style
 
@@ -411,9 +411,9 @@ func DefaultStyles() *Styles {
 
 	s.SpinnerContainer = lipgloss.NewStyle()
 
-	s.CodeNoContent = lipgloss.NewStyle().
+	s.NoContent = lipgloss.NewStyle().
 		SetString("No Content.").
-		MarginTop(1).
+		MarginTop(2).
 		MarginLeft(2).
 		Foreground(lipgloss.Color("242"))