Skip to content

Commit 074b070

Browse files
authored
feat: dates in inbox (#267)
1 parent 5f6aa00 commit 074b070

1 file changed

Lines changed: 74 additions & 1 deletion

File tree

tui/inbox.go

Lines changed: 74 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"fmt"
55
"io"
66
"strings"
7+
"time"
78

89
"charm.land/bubbles/v2/key"
910
"charm.land/bubbles/v2/list"
@@ -22,12 +23,15 @@ var (
2223
tabBarStyle = lipgloss.NewStyle().BorderStyle(lipgloss.NormalBorder()).BorderBottom(true).PaddingBottom(1).MarginBottom(1)
2324
)
2425

26+
var dateStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("243"))
27+
2528
type item struct {
2629
title, desc string
2730
originalIndex int
2831
uid uint32
2932
accountID string
3033
accountEmail string
34+
date time.Time
3135
}
3236

3337
func (i item) Title() string { return i.title }
@@ -52,14 +56,82 @@ func (d itemDelegate) Render(w io.Writer, m list.Model, index int, listItem list
5256
str = fmt.Sprintf("%d. [%s] %s", index+1, truncateEmail(i.accountEmail), i.title)
5357
}
5458

59+
// Format and right-align date
60+
dateStr := formatRelativeDate(i.date)
61+
styledDate := dateStyle.Render(dateStr)
62+
dateWidth := lipgloss.Width(styledDate)
63+
64+
// Truncate the left part to fit within the available width
65+
listWidth := m.Width()
66+
isSelected := index == m.Index()
67+
cursorWidth := 0
68+
if isSelected {
69+
cursorWidth = 2 // "> " prefix
70+
}
71+
maxLeft := listWidth - dateWidth - 2 - cursorWidth // 2 for spacing
72+
if maxLeft < 10 {
73+
maxLeft = 10
74+
}
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]
79+
}
80+
str += "…"
81+
}
82+
83+
// Pad to push date to the right
84+
padding := listWidth - lipgloss.Width(str) - dateWidth - cursorWidth
85+
if padding < 1 {
86+
padding = 1
87+
}
88+
5589
fn := itemStyle.Render
5690
if index == m.Index() {
5791
fn = func(s ...string) string {
5892
return selectedItemStyle.Render("> " + s[0])
5993
}
6094
}
6195

62-
fmt.Fprint(w, fn(str))
96+
fmt.Fprint(w, fn(str+strings.Repeat(" ", padding)+styledDate))
97+
}
98+
99+
// formatRelativeDate formats a time as relative if within the last week,
100+
// otherwise as an absolute date.
101+
func formatRelativeDate(t time.Time) string {
102+
if t.IsZero() {
103+
return ""
104+
}
105+
now := time.Now()
106+
d := now.Sub(t)
107+
108+
switch {
109+
case d < time.Minute:
110+
return "just now"
111+
case d < time.Hour:
112+
mins := int(d.Minutes())
113+
if mins == 1 {
114+
return "1 min ago"
115+
}
116+
return fmt.Sprintf("%d min ago", mins)
117+
case d < 24*time.Hour:
118+
hours := int(d.Hours())
119+
if hours == 1 {
120+
return "1 hour ago"
121+
}
122+
return fmt.Sprintf("%d hours ago", hours)
123+
case d < 7*24*time.Hour:
124+
days := int(d.Hours() / 24)
125+
if days == 1 {
126+
return "1 day ago"
127+
}
128+
return fmt.Sprintf("%d days ago", days)
129+
default:
130+
if t.Year() == now.Year() {
131+
return t.Format("Jan 02")
132+
}
133+
return t.Format("Jan 02, 2006")
134+
}
63135
}
64136

65137
// truncateEmail shortens an email for display
@@ -205,6 +277,7 @@ func (m *Inbox) updateList() {
205277
uid: email.UID,
206278
accountID: email.AccountID,
207279
accountEmail: accountEmail,
280+
date: email.Date,
208281
}
209282
}
210283

0 commit comments

Comments
 (0)