feat(tui-go): show last-activity date in the starting-view session list

The idle "sessions" panel listed id/status/name/stage but no time at all. Add a
right-aligned last-activity timestamp (Session.LastEventAt) per row — "Jan 02
15:04" within the current year, "Jan 02 2006" for older — so old sessions are
distinguishable at a glance. The name is truncated first so the box's width
clamp never eats the date column. (The R resume overlay already shows a relative
age; this is the live list on the starting screen.)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-22 10:04:41 +00:00
parent 85121cec9d
commit 454f24fc3a
+35 -4
View File
@@ -4,6 +4,7 @@ import (
"fmt"
"os"
"strings"
"time"
"github.com/charmbracelet/lipgloss"
"github.com/charmbracelet/x/ansi"
@@ -431,16 +432,46 @@ func (m Model) sessionRows(w int) []string {
idCell := t.span("["+short+"] ", t.P.Faint)
statusCell := lipgloss.NewStyle().Foreground(statusColor(t, s.Status)).Background(t.P.Bg).Bold(true).
Render(padRaw(statusLabel(s.Status), 9))
nameCell := lipgloss.NewStyle().Foreground(nameFg).Background(t.P.Bg).Render(" " + s.Name)
stage := ""
stageStr := ""
if s.CurrentStage != "" {
stage = t.span(" ["+s.CurrentStage+"]", t.P.Dim)
stageStr = " [" + s.CurrentStage + "]"
}
rows = append(rows, bar+idCell+statusCell+nameCell+stage)
dateCell := t.span(shortDateTime(s.LastEventAt), t.P.Faint)
// Right-align the last-activity date; truncate the name first so the date column
// always survives the box's width clamp (padTo) even on a slim panel.
fixed := lipgloss.Width(bar) + lipgloss.Width(idCell) + lipgloss.Width(statusCell) + 1 + len([]rune(stageStr))
name := s.Name
if budget := w - fixed - lipgloss.Width(dateCell) - 1; budget >= 1 && len([]rune(name)) > budget {
name = truncate(name, budget)
}
nameCell := lipgloss.NewStyle().Foreground(nameFg).Background(t.P.Bg).Render(" " + name)
stageCell := t.span(stageStr, t.P.Dim)
left := bar + idCell + statusCell + nameCell + stageCell
gap := w - lipgloss.Width(left) - lipgloss.Width(dateCell)
if gap < 1 {
gap = 1
}
rows = append(rows, left+t.span(strings.Repeat(" ", gap), t.P.Bg)+dateCell)
}
return rows
}
// shortDateTime formats a millis-since-epoch instant as a compact local timestamp for the
// session list: "Jan 02 15:04" within the current year, "Jan 02 2006" for older years.
// Empty for a zero/absent time (renders as no date rather than a bogus epoch).
func shortDateTime(ms int64) string {
if ms <= 0 {
return ""
}
ts := time.UnixMilli(ms)
if ts.Year() != time.Now().Year() {
return ts.Format("Jan 02 2006")
}
return ts.Format("Jan 02 15:04")
}
func (m Model) workflowRows(w int) []string {
t := m.theme
if len(m.workflows) == 0 {