diff options
| author | Kyren223 <Kyren223@proton.me> | 2024-11-03 19:33:30 +0200 |
|---|---|---|
| committer | Kyren223 <Kyren223@proton.me> | 2024-11-03 19:33:30 +0200 |
| commit | ff3140a4089819489130a0908178a63eff20f708 (patch) | |
| tree | def568e1deca7461f814e55af7d9e09720e0b0ae /internal/client/ui/messagebox | |
| parent | a637ea9c335c385985a23510a4174d837fb51faf (diff) | |
feat: add username and timestamp to messages
Diffstat (limited to 'internal/client/ui/messagebox')
| -rw-r--r-- | internal/client/ui/messagebox/messagebox.go | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/internal/client/ui/messagebox/messagebox.go b/internal/client/ui/messagebox/messagebox.go new file mode 100644 index 0000000..4b8d3d1 --- /dev/null +++ b/internal/client/ui/messagebox/messagebox.go @@ -0,0 +1,132 @@ +package messagebox + +import ( + "slices" + "strings" + "time" + + "github.com/charmbracelet/bubbles/viewport" + tea "github.com/charmbracelet/bubbletea" + "github.com/charmbracelet/lipgloss" + + "github.com/kyren223/eko/internal/client/api" + "github.com/kyren223/eko/internal/data" + "github.com/kyren223/eko/pkg/snowflake" +) + +type user struct { + name string + isFetching bool +} + +type Model struct { + Viewport viewport.Model + messages []data.Message + + senderStyle lipgloss.Style + timestampStyle lipgloss.Style + + users map[snowflake.ID]user +} + +func New(width, height int) Model { + return Model{ + Viewport: viewport.New(width, height), + messages: nil, + senderStyle: lipgloss.NewStyle().Foreground(lipgloss.Color("5")).Bold(true), + timestampStyle: lipgloss.NewStyle().Foreground(lipgloss.Color("#585c62")).Italic(true), + users: make(map[snowflake.ID]user), + } +} + +func (m Model) Init() tea.Cmd { + return api.GetMessages +} + +func (m Model) View() string { + return m.Viewport.View() +} + +func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) { + var cmds []tea.Cmd + + for id, user := range m.users { + if !user.isFetching && user.name == "" { + cmds = append(cmds, api.GetUserById(id)) + user.isFetching = true + m.users[id] = user + } + } + + var cmd tea.Cmd + m.Viewport, cmd = m.Viewport.Update(msg) + cmds = append(cmds, cmd) + + switch msg := msg.(type) { + case api.UserProfileUpdate: + m.users[msg.ID] = user{msg.Name, false} + m.UpdateMessages() + } + + return m, tea.Batch(cmds...) +} + +func (m *Model) AppendMessage(message data.Message) { + m.messages = append(m.messages, message) + m.UpdateMessages() +} + +func (m *Model) SetMessages(messages []data.Message) { + m.messages = messages + m.UpdateMessages() +} + +func (m *Model) UpdateMessages() { + for _, message := range m.messages { + if _, exists := m.users[message.SenderID]; !exists { + m.users[message.SenderID] = user{name: "", isFetching: false} + } + } + + m.sortMessages() + m.updateContent() + m.Viewport.GotoBottom() +} + +func (m *Model) sortMessages() { + slices.SortFunc(m.messages, func(a, b data.Message) int { + if a.ID-b.ID < 0 { + return -1 + } else { + return 1 + } + }) +} + +func (m *Model) updateContent() { + if len(m.messages) == 0 { + return + } + + var builder strings.Builder + + for _, message := range m.messages { + sender := m.users[message.SenderID].name + builder.WriteString(m.senderStyle.Render(sender)) + builder.WriteByte(' ') + + timestamp := timestampFromID(message.ID) + builder.WriteString(m.timestampStyle.Render(timestamp)) + builder.WriteByte('\n') + + builder.WriteString(message.Content) + builder.WriteByte('\n') + } + + m.Viewport.SetContent(builder.String()[:builder.Len()-1]) +} + +func timestampFromID(id snowflake.ID) string { + localTime := time.UnixMilli(id.Time()) + return localTime.Format("02/01/2006 3:04 PM") +} |
