feat: new log item style

Ayman Bagabas created

Change summary

ui/components/statusbar/statusbar.go |  7 +
ui/pages/repo/log.go                 |  7 +-
ui/pages/repo/logitem.go             | 81 ++++++++++++++++++++++++-----
ui/styles/styles.go                  | 45 ++++++++++-----
4 files changed, 102 insertions(+), 38 deletions(-)

Detailed changes

ui/components/statusbar/statusbar.go 🔗

@@ -4,6 +4,7 @@ import (
 	tea "github.com/charmbracelet/bubbletea"
 	"github.com/charmbracelet/lipgloss"
 	"github.com/charmbracelet/soft-serve/ui/common"
+	"github.com/muesli/reflow/truncate"
 )
 
 type StatusBarMsg struct {
@@ -56,9 +57,11 @@ func (s *StatusBar) View() string {
 		info = st.StatusBarInfo.Render(s.msg.Info)
 	}
 	branch := st.StatusBarBranch.Render(s.msg.Branch)
+	maxWidth := s.common.Width - w(key) - w(info) - w(branch)
+	v := truncate.StringWithTail(s.msg.Value, uint(maxWidth-st.StatusBarValue.GetHorizontalFrameSize()), "…")
 	value := st.StatusBarValue.
-		Width(s.common.Width - w(key) - w(info) - w(branch)).
-		Render(s.msg.Value)
+		Width(maxWidth).
+		Render(v)
 
 	return lipgloss.JoinHorizontal(lipgloss.Top,
 		key,

ui/pages/repo/log.go 🔗

@@ -274,10 +274,9 @@ func (l *Log) StatusBarValue() string {
 	if c == nil {
 		return ""
 	}
-	return fmt.Sprintf("%s by %s on %s",
-		c.ID.String()[:7],
-		c.Author.Name,
-		c.Author.When.Format("02 Jan 2006"),
+	return fmt.Sprintf("%s by %s",
+		c.ID.String(),
+		fmt.Sprintf("%s <%s>", c.Author.Name, c.Author.Email),
 	)
 }
 

ui/pages/repo/logitem.go 🔗

@@ -4,9 +4,11 @@ import (
 	"fmt"
 	"io"
 	"strings"
+	"time"
 
 	"github.com/charmbracelet/bubbles/list"
 	tea "github.com/charmbracelet/bubbletea"
+	"github.com/charmbracelet/lipgloss"
 	"github.com/charmbracelet/soft-serve/git"
 	"github.com/charmbracelet/soft-serve/ui/styles"
 	"github.com/muesli/reflow/truncate"
@@ -42,10 +44,10 @@ type LogItemDelegate struct {
 }
 
 // Height returns the item height. Implements list.ItemDelegate.
-func (d LogItemDelegate) Height() int { return 1 }
+func (d LogItemDelegate) Height() int { return 2 }
 
 // Spacing returns the item spacing. Implements list.ItemDelegate.
-func (d LogItemDelegate) Spacing() int { return 0 }
+func (d LogItemDelegate) Spacing() int { return 1 }
 
 // Update updates the item. Implements list.ItemDelegate.
 func (d LogItemDelegate) Update(msg tea.Msg, m *list.Model) tea.Cmd { return nil }
@@ -60,22 +62,69 @@ func (d LogItemDelegate) Render(w io.Writer, m list.Model, index int, listItem l
 		return
 	}
 
-	hash := i.Commit.ID.String()
-	leftMargin := d.style.LogItemSelector.GetMarginLeft() +
-		d.style.LogItemSelector.GetWidth() +
-		d.style.LogItemHash.GetMarginLeft() +
-		d.style.LogItemHash.GetWidth() +
-		d.style.LogItemInactive.GetMarginLeft()
-	title := truncateString(i.Title(), m.Width()-leftMargin, "…")
+	width := lipgloss.Width
+	titleStyle := d.style.LogItemTitle.Copy()
+	style := d.style.LogItemInactive
 	if index == m.Index() {
-		fmt.Fprint(w, d.style.LogItemSelector.Render(">")+
-			d.style.LogItemHash.Bold(true).Render(hash[:7])+
-			d.style.LogItemActive.Render(title))
-	} else {
-		fmt.Fprint(w, d.style.LogItemSelector.Render(" ")+
-			d.style.LogItemHash.Render(hash[:7])+
-			d.style.LogItemInactive.Render(title))
+		titleStyle.Bold(true)
+		style = d.style.LogItemActive
 	}
+	hash := " " + i.Commit.ID.String()[:7]
+	title := titleStyle.Render(
+		truncateString(i.Title(), m.Width()-style.GetHorizontalFrameSize()-width(hash)-2, "…"),
+	)
+	hash = d.style.LogItemHash.Copy().
+		Align(lipgloss.Right).
+		Width(m.Width() -
+			style.GetHorizontalFrameSize() -
+			width(title) -
+			// FIXME where this "1" is coming from?
+			1).
+		Render(hash)
+	author := i.Author.Name
+	commiter := i.Committer.Name
+	who := ""
+	if author != "" && commiter != "" {
+		who = fmt.Sprintf("%s committed", commiter)
+		if author != commiter {
+			who = fmt.Sprintf("%s authored and %s", author, who)
+		}
+		who += " "
+	}
+	date := fmt.Sprintf("on %s", i.Committer.When.Format("Feb 02"))
+	if i.Committer.When.Year() != time.Now().Year() {
+		date += fmt.Sprintf(" %d", i.Committer.When.Year())
+	}
+	who += date
+	who = truncateString(who, m.Width()-style.GetHorizontalFrameSize(), "…")
+	fmt.Fprint(w,
+		style.Render(
+			lipgloss.JoinVertical(lipgloss.Top,
+				lipgloss.JoinHorizontal(lipgloss.Left,
+					title,
+					hash,
+				),
+				who,
+			),
+		),
+	)
+
+	// leftMargin := d.style.LogItemSelector.GetMarginLeft() +
+	// 	d.style.LogItemSelector.GetWidth() +
+	// 	d.style.LogItemHash.GetMarginLeft() +
+	// 	d.style.LogItemHash.GetWidth() +
+	// 	d.style.LogItemInactive.GetMarginLeft()
+	// title := truncateString(i.Title(), m.Width()-leftMargin, "…")
+	// if index == m.Index() {
+	// 	fmt.Fprint(w, d.style.LogItemSelector.Render(">")+
+	// 		d.style.LogItemHash.Bold(true).Render(hash[:7])+
+	// 		d.style.LogItemActive.Render(title))
+	// } else {
+	// 	fmt.Fprint(w, d.style.LogItemSelector.Render(" ")+
+	// 		d.style.LogItemHash.Render(hash[:7])+
+	// 		d.style.LogItemInactive.Render(title))
+	// }
+	// fmt.Fprintln(w)
 }
 
 func truncateString(s string, max int, tail string) string {

ui/styles/styles.go 🔗

@@ -50,10 +50,12 @@ type Styles struct {
 
 	AboutNoReadme lipgloss.Style
 
+	LogItem           lipgloss.Style
 	LogItemSelector   lipgloss.Style
 	LogItemActive     lipgloss.Style
 	LogItemInactive   lipgloss.Style
 	LogItemHash       lipgloss.Style
+	LogItemTitle      lipgloss.Style
 	LogCommit         lipgloss.Style
 	LogCommitHash     lipgloss.Style
 	LogCommitAuthor   lipgloss.Style
@@ -245,25 +247,32 @@ func DefaultStyles() *Styles {
 		Foreground(lipgloss.Color("#626262"))
 
 	s.LogItemInactive = lipgloss.NewStyle().
-		MarginLeft(1)
+		Border(lipgloss.Border{
+			Left: " ",
+		}, false, false, false, true).
+		PaddingLeft(1)
+
+	s.LogItemActive = s.LogItemInactive.Copy().
+		Border(lipgloss.Border{
+			Left: "│",
+		}, false, false, false, true).
+		BorderForeground(lipgloss.Color("#B083EA"))
 
 	s.LogItemSelector = s.LogItemInactive.Copy().
 		Width(1).
 		Foreground(lipgloss.Color("#B083EA"))
 
-	s.LogItemActive = s.LogItemInactive.Copy().
-		Bold(true)
-
 	s.LogItemHash = s.LogItemInactive.Copy().
-		Width(7).
 		Foreground(lipgloss.Color("#A3A322"))
 
+	s.LogItemTitle = lipgloss.NewStyle().
+		Foreground(lipgloss.Color("#B083EA"))
+
 	s.LogCommit = lipgloss.NewStyle().
 		Margin(0, 2)
 
-	s.LogCommitHash = s.LogItemHash.Copy().
-		UnsetMarginLeft().
-		UnsetWidth().
+	s.LogCommitHash = lipgloss.NewStyle().
+		Foreground(lipgloss.Color("#A3A322")).
 		Bold(true)
 
 	s.LogCommitBody = lipgloss.NewStyle().
@@ -282,11 +291,11 @@ func DefaultStyles() *Styles {
 		Margin(0).
 		Align(lipgloss.Center)
 
-	s.RefItemSelector = s.LogItemSelector.Copy()
+	s.RefItemSelector = s.TreeItemSelector.Copy()
 
-	s.RefItemActive = s.LogItemActive.Copy()
+	s.RefItemActive = s.TreeItemActive.Copy()
 
-	s.RefItemInactive = s.LogItemInactive.Copy()
+	s.RefItemInactive = s.TreeItemInactive.Copy()
 
 	s.RefItemBranch = lipgloss.NewStyle()
 
@@ -295,20 +304,24 @@ func DefaultStyles() *Styles {
 
 	s.RefPaginator = s.LogPaginator.Copy()
 
-	s.TreeItemSelector = s.LogItemSelector.Copy()
+	s.TreeItemSelector = s.TreeItemInactive.Copy().
+		Width(1).
+		Foreground(lipgloss.Color("#B083EA"))
 
-	s.TreeItemActive = s.LogItemActive.Copy()
+	s.TreeItemInactive = lipgloss.NewStyle().
+		MarginLeft(1)
 
-	s.TreeItemInactive = s.LogItemInactive.Copy()
+	s.TreeItemActive = s.TreeItemInactive.Copy().
+		Bold(true)
 
 	s.TreeFileDir = lipgloss.NewStyle().
 		Foreground(lipgloss.Color("#00AAFF"))
 
-	s.TreeFileMode = s.LogItemInactive.Copy().
+	s.TreeFileMode = s.TreeItemInactive.Copy().
 		Width(10).
 		Foreground(lipgloss.Color("#777777"))
 
-	s.TreeFileSize = s.LogItemInactive.Copy().
+	s.TreeFileSize = s.TreeItemInactive.Copy().
 		Foreground(lipgloss.Color("252"))
 
 	s.TreeFileContent = lipgloss.NewStyle()