tui: cleanup conversations data model
This commit is contained in:
parent
1404cae6a7
commit
0e68e22efa
@ -13,17 +13,21 @@ import (
|
|||||||
"github.com/charmbracelet/lipgloss"
|
"github.com/charmbracelet/lipgloss"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type loadedConversation struct {
|
||||||
|
conv models.Conversation
|
||||||
|
lastReply models.Message
|
||||||
|
}
|
||||||
|
|
||||||
type (
|
type (
|
||||||
// send when conversation list is loaded
|
// sent when conversation list is loaded
|
||||||
msgConversationsLoaded []models.Conversation
|
msgConversationsLoaded ([]loadedConversation)
|
||||||
|
// sent when each coversation's 'last reply' is loaded
|
||||||
)
|
)
|
||||||
|
|
||||||
type conversationsModel struct {
|
type conversationsModel struct {
|
||||||
basemodel
|
basemodel
|
||||||
|
|
||||||
conversations []models.Conversation
|
conversations []loadedConversation
|
||||||
lastReplies []models.Message
|
|
||||||
|
|
||||||
content viewport.Model
|
content viewport.Model
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,23 +106,28 @@ func (m conversationsModel) Update(msg tea.Msg) (conversationsModel, tea.Cmd) {
|
|||||||
|
|
||||||
func (m *conversationsModel) loadConversations() tea.Cmd {
|
func (m *conversationsModel) loadConversations() tea.Cmd {
|
||||||
return func() tea.Msg {
|
return func() tea.Msg {
|
||||||
c, err := m.ctx.Store.Conversations()
|
conversations, err := m.ctx.Store.Conversations()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return msgError(fmt.Errorf("Could not load conversations: %v", err))
|
return msgError(fmt.Errorf("Could not load conversations: %v", err))
|
||||||
}
|
}
|
||||||
return msgConversationsLoaded(c)
|
|
||||||
|
loaded := make([]loadedConversation, len(conversations))
|
||||||
|
for i, c := range conversations {
|
||||||
|
lastMessage, err := m.ctx.Store.LastMessage(&c)
|
||||||
|
if err != nil {
|
||||||
|
return msgError(err)
|
||||||
}
|
}
|
||||||
|
loaded[i].conv = c
|
||||||
|
loaded[i].lastReply = *lastMessage
|
||||||
}
|
}
|
||||||
|
|
||||||
//func (m *conversationsModel) loadConversationLastestReplies(conversations []models.Conversation) tea.Cmd {
|
slices.SortFunc(loaded, func(a, b loadedConversation) int {
|
||||||
// return func() tea.Msg {
|
return b.lastReply.CreatedAt.Compare(a.lastReply.CreatedAt)
|
||||||
// //lastMessage, err := m.ctx.Store.LastMessage(&conversation)
|
})
|
||||||
// return nil
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
//func (m *conversationsModel) setConversations(conversations []models.Conversation) {
|
return msgConversationsLoaded(loaded)
|
||||||
//}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (m *conversationsModel) headerView() string {
|
func (m *conversationsModel) headerView() string {
|
||||||
titleStyle := lipgloss.NewStyle().Bold(true)
|
titleStyle := lipgloss.NewStyle().Bold(true)
|
||||||
@ -127,13 +136,12 @@ func (m *conversationsModel) headerView() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m *conversationsModel) renderConversationList() string {
|
func (m *conversationsModel) renderConversationList() string {
|
||||||
sb := &strings.Builder{}
|
type timeCategory struct {
|
||||||
type AgeGroup struct {
|
|
||||||
name string
|
name string
|
||||||
cutoff time.Duration
|
cutoff time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
type ConversationLine struct {
|
type listItem struct {
|
||||||
id uint
|
id uint
|
||||||
short string
|
short string
|
||||||
title string
|
title string
|
||||||
@ -142,11 +150,10 @@ func (m *conversationsModel) renderConversationList() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
|
|
||||||
midnight := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location())
|
midnight := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location())
|
||||||
monthStart := time.Date(now.Year(), now.Month(), 1, 0, 0, 0, 0, now.Location())
|
monthStart := time.Date(now.Year(), now.Month(), 1, 0, 0, 0, 0, now.Location())
|
||||||
dayOfWeek := int(now.Weekday())
|
dayOfWeek := int(now.Weekday())
|
||||||
categories := []AgeGroup{
|
categories := []timeCategory{
|
||||||
{"Today", now.Sub(midnight)},
|
{"Today", now.Sub(midnight)},
|
||||||
{"Yesterday", now.Sub(midnight.AddDate(0, 0, -1))},
|
{"Yesterday", now.Sub(midnight.AddDate(0, 0, -1))},
|
||||||
{"This week", now.Sub(midnight.AddDate(0, 0, -dayOfWeek))},
|
{"This week", now.Sub(midnight.AddDate(0, 0, -dayOfWeek))},
|
||||||
@ -160,32 +167,6 @@ func (m *conversationsModel) renderConversationList() string {
|
|||||||
{"6 Months ago", now.Sub(monthStart.AddDate(0, -6, 0))},
|
{"6 Months ago", now.Sub(monthStart.AddDate(0, -6, 0))},
|
||||||
{"Older", now.Sub(time.Time{})},
|
{"Older", now.Sub(time.Time{})},
|
||||||
}
|
}
|
||||||
categorized := map[string][]ConversationLine{}
|
|
||||||
|
|
||||||
for _, conversation := range m.conversations {
|
|
||||||
lastMessage, err := m.ctx.Store.LastMessage(&conversation)
|
|
||||||
if lastMessage == nil || err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
messageAge := now.Sub(lastMessage.CreatedAt)
|
|
||||||
var category string
|
|
||||||
for _, c := range categories {
|
|
||||||
if messageAge < c.cutoff {
|
|
||||||
category = c.name
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
categorized[category] = append(
|
|
||||||
categorized[category],
|
|
||||||
ConversationLine{
|
|
||||||
id: conversation.ID,
|
|
||||||
title: conversation.Title,
|
|
||||||
short: conversation.ShortName.String,
|
|
||||||
lastReplyAge: messageAge,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: pick nice color
|
// TODO: pick nice color
|
||||||
categoryStyle := lipgloss.NewStyle().
|
categoryStyle := lipgloss.NewStyle().
|
||||||
@ -198,35 +179,39 @@ func (m *conversationsModel) renderConversationList() string {
|
|||||||
MarginBottom(1).
|
MarginBottom(1).
|
||||||
PaddingLeft(2)
|
PaddingLeft(2)
|
||||||
|
|
||||||
for _, category := range categories {
|
|
||||||
conversationLines, ok := categorized[category.name]
|
|
||||||
if !ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
slices.SortFunc(conversationLines, func(a, b ConversationLine) int {
|
|
||||||
return int(a.lastReplyAge - b.lastReplyAge)
|
|
||||||
})
|
|
||||||
|
|
||||||
ageStyle := lipgloss.NewStyle().Faint(true)
|
ageStyle := lipgloss.NewStyle().Faint(true)
|
||||||
titleStyle := lipgloss.NewStyle().Bold(true)
|
titleStyle := lipgloss.NewStyle().Bold(true)
|
||||||
untitledStyle := titleStyle.Copy().Italic(true).SetString("(untitled)")
|
untitledStyle := titleStyle.Copy().Italic(true).Faint(true).SetString("(untitled)")
|
||||||
|
|
||||||
|
var currentCategory string
|
||||||
|
sb := &strings.Builder{}
|
||||||
|
for _, c := range m.conversations {
|
||||||
|
lastReplyAge := now.Sub(c.lastReply.CreatedAt)
|
||||||
|
|
||||||
|
var category string
|
||||||
|
for _, g := range categories {
|
||||||
|
if lastReplyAge < g.cutoff {
|
||||||
|
category = g.name
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if category != currentCategory {
|
||||||
|
currentCategory = category
|
||||||
|
fmt.Fprintf(sb, "%s\n", categoryStyle.Render(currentCategory))
|
||||||
|
}
|
||||||
|
|
||||||
fmt.Fprintf(sb, "%s\n", categoryStyle.Render(category.name))
|
|
||||||
for _, c := range conversationLines {
|
|
||||||
tstyle := titleStyle
|
tstyle := titleStyle
|
||||||
if c.title == "" {
|
if c.conv.Title == "" {
|
||||||
tstyle = untitledStyle
|
tstyle = untitledStyle
|
||||||
}
|
}
|
||||||
heading := fmt.Sprintf(
|
heading := fmt.Sprintf(
|
||||||
"%s\n%s",
|
"%s\n%s",
|
||||||
tstyle.Render(c.title),
|
tstyle.Render(c.conv.Title),
|
||||||
ageStyle.Render(util.HumanTimeElapsedSince(c.lastReplyAge)),
|
ageStyle.Render(util.HumanTimeElapsedSince(lastReplyAge)),
|
||||||
)
|
)
|
||||||
sb.WriteString(conversationHeadingStyle.Render(heading))
|
sb.WriteString(conversationHeadingStyle.Render(heading))
|
||||||
sb.WriteRune('\n')
|
sb.WriteRune('\n')
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return sb.String()
|
return sb.String()
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user