package main import ( "fmt" "strings" "time" "github.com/charmbracelet/lipgloss" ) // RenderMessages renders the chat message list for the viewport. func RenderMessages(messages []Message, width int, currentUser string) string { if len(messages) == 0 { return HelpStyle.Render(" No messages yet. Press 'i' to type a message.") } var lines []string for _, msg := range messages { ts := formatTimestamp(msg.CreatedAt) // Determine display name displayName := msg.AuthorName if msg.DisplayName != nil && *msg.DisplayName != "" { displayName = *msg.DisplayName } // Color the username userColor := UsernameColor(msg.AuthorName) styledUser := UsernameStyle.Foreground(userColor).Render(displayName) // Content content := msg.Content // Show edited tag editedTag := "" if msg.EditedAt != nil { editedTag = EditedTag.Render(" (edited)") } // IRC-style: [HH:MM] message tsRendered := TimestampStyle.Render("[" + ts + "]") prefix := fmt.Sprintf("%s <%s> ", tsRendered, styledUser) // Word wrap the content contentWidth := width - lipgloss.Width(prefix) - 2 if contentWidth < 10 { contentWidth = 40 } wrappedContent := wordWrap(content, contentWidth) // First line has the prefix, continuation lines are indented contentLines := strings.Split(wrappedContent, "\n") for i, cl := range contentLines { if i == 0 { lines = append(lines, prefix+cl+editedTag) } else { indent := strings.Repeat(" ", lipgloss.Width(prefix)) lines = append(lines, indent+cl) } } } return strings.Join(lines, "\n") } // formatTimestamp parses the created_at string and returns HH:MM. func formatTimestamp(ts string) string { // Try various formats the server might return formats := []string{ time.RFC3339, "2006-01-02T15:04:05.999999Z", "2006-01-02T15:04:05.999999-07:00", "2006-01-02 15:04:05", "2006-01-02T15:04:05Z", } for _, f := range formats { if t, err := time.Parse(f, ts); err == nil { return t.Format("15:04") } } // Fallback: try to extract HH:MM from the string if len(ts) >= 16 { return ts[11:16] } return "??:??" } // wordWrap wraps text to the given width. func wordWrap(text string, width int) string { if width <= 0 { return text } words := strings.Fields(text) if len(words) == 0 { return "" } var lines []string currentLine := words[0] for _, word := range words[1:] { if len(currentLine)+1+len(word) > width { lines = append(lines, currentLine) currentLine = word } else { currentLine += " " + word } } lines = append(lines, currentLine) return strings.Join(lines, "\n") }