2323 tabBarStyle = lipgloss .NewStyle ().BorderStyle (lipgloss .NormalBorder ()).BorderBottom (true ).PaddingBottom (1 ).MarginBottom (1 )
2424)
2525
26- var dateStyle = lipgloss .NewStyle ().Foreground (lipgloss .Color ("243" ))
26+ var dateStyle = lipgloss .NewStyle ().Foreground (lipgloss .Color ("243" ))
27+ var senderStyle = lipgloss .NewStyle ().Foreground (lipgloss .Color ("250" )).Bold (true )
2728
2829type item struct {
2930 title , desc string
@@ -49,37 +50,52 @@ func (d itemDelegate) Render(w io.Writer, m list.Model, index int, listItem list
4950 return
5051 }
5152
52- str := fmt .Sprintf ("%d. %s" , index + 1 , i .title )
53+ prefix := fmt .Sprintf ("%d. " , index + 1 )
54+ sender := parseSenderName (i .desc )
55+ styledSender := senderStyle .Render (sender )
56+ separator := " · "
5357
54- // For "ALL" view, show account indicator
58+ // For "ALL" view, show account indicator instead of number
5559 if i .accountEmail != "" {
56- str = fmt .Sprintf ("%d. [%s] %s " , index + 1 , truncateEmail (i .accountEmail ), i . title )
60+ prefix = fmt .Sprintf ("%d. [%s] " , index + 1 , truncateEmail (i .accountEmail ))
5761 }
5862
5963 // Format and right-align date
6064 dateStr := formatRelativeDate (i .date )
6165 styledDate := dateStyle .Render (dateStr )
6266 dateWidth := lipgloss .Width (styledDate )
6367
64- // Truncate the left part to fit within the available width
6568 listWidth := m .Width ()
6669 isSelected := index == m .Index ()
6770 cursorWidth := 0
6871 if isSelected {
6972 cursorWidth = 2 // "> " prefix
7073 }
74+
75+ // Available width for the whole left side (prefix + sender + separator + subject)
7176 maxLeft := listWidth - dateWidth - 2 - cursorWidth // 2 for spacing
7277 if maxLeft < 10 {
7378 maxLeft = 10
7479 }
75- if lipgloss .Width (str ) > maxLeft {
76- // Truncate with ellipsis
77- for lipgloss .Width (str ) > maxLeft - 1 && len (str ) > 0 {
78- str = str [:len (str )- 1 ]
80+
81+ prefixWidth := lipgloss .Width (prefix )
82+ senderWidth := lipgloss .Width (styledSender )
83+ sepWidth := len (separator )
84+ subjectBudget := maxLeft - prefixWidth - senderWidth - sepWidth
85+
86+ subject := i .title
87+ if subjectBudget < 4 {
88+ subjectBudget = 4
89+ }
90+ if lipgloss .Width (subject ) > subjectBudget {
91+ for lipgloss .Width (subject ) > subjectBudget - 1 && len (subject ) > 0 {
92+ subject = subject [:len (subject )- 1 ]
7993 }
80- str += "…"
94+ subject += "…"
8195 }
8296
97+ str := prefix + styledSender + separator + subject
98+
8399 // Pad to push date to the right
84100 padding := listWidth - lipgloss .Width (str ) - dateWidth - cursorWidth
85101 if padding < 1 {
@@ -134,6 +150,19 @@ func formatRelativeDate(t time.Time) string {
134150 }
135151}
136152
153+ // parseSenderName extracts the display name from a "Name <email>" string,
154+ // falling back to the local part of the email address.
155+ func parseSenderName (from string ) string {
156+ if idx := strings .Index (from , " <" ); idx > 0 {
157+ return strings .TrimSpace (from [:idx ])
158+ }
159+ // No display name — use local part of email
160+ if idx := strings .Index (from , "@" ); idx > 0 {
161+ return from [:idx ]
162+ }
163+ return from
164+ }
165+
137166// truncateEmail shortens an email for display
138167func truncateEmail (email string ) string {
139168 parts := strings .Split (email , "@" )
0 commit comments