1package messages
2
3import (
4 "fmt"
5
6 tea "github.com/charmbracelet/bubbletea"
7 "github.com/charmbracelet/lipgloss"
8 "github.com/cloudwego/eino/schema"
9 "github.com/kujtimiihoxha/termai/internal/message"
10 "github.com/kujtimiihoxha/termai/internal/tui/layout"
11 "github.com/kujtimiihoxha/termai/internal/tui/styles"
12)
13
14const (
15 maxHeight = 10
16)
17
18type MessagesCmp interface {
19 tea.Model
20 layout.Focusable
21 layout.Bordered
22 layout.Sizeable
23}
24
25type messageCmp struct {
26 message message.Message
27 width int
28 height int
29 focused bool
30 expanded bool
31}
32
33func (m *messageCmp) Init() tea.Cmd {
34 return nil
35}
36
37func (m *messageCmp) Update(tea.Msg) (tea.Model, tea.Cmd) {
38 return m, nil
39}
40
41func (m *messageCmp) View() string {
42 wrapper := layout.NewSinglePane(
43 m,
44 layout.WithSinglePaneBordered(true),
45 layout.WithSinglePaneFocusable(true),
46 layout.WithSinglePanePadding(1),
47 layout.WithSinglePaneActiveColor(m.borderColor()),
48 )
49 if m.focused {
50 wrapper.Focus()
51 }
52 wrapper.SetSize(m.width, m.height)
53 return wrapper.View()
54}
55
56func (m *messageCmp) Blur() tea.Cmd {
57 m.focused = false
58 return nil
59}
60
61func (m *messageCmp) borderColor() lipgloss.TerminalColor {
62 switch m.message.MessageData.Role {
63 case schema.Assistant:
64 return styles.Mauve
65 case schema.User:
66 return styles.Flamingo
67 }
68 return styles.Blue
69}
70
71func (m *messageCmp) BorderText() map[layout.BorderPosition]string {
72 role := ""
73 icon := ""
74 switch m.message.MessageData.Role {
75 case schema.Assistant:
76 role = "Assistant"
77 icon = styles.BotIcon
78 case schema.User:
79 role = "User"
80 icon = styles.UserIcon
81 }
82 return map[layout.BorderPosition]string{
83 layout.TopLeftBorder: fmt.Sprintf("%s %s ", role, icon),
84 }
85}
86
87func (m *messageCmp) Focus() tea.Cmd {
88 m.focused = true
89 return nil
90}
91
92func (m *messageCmp) IsFocused() bool {
93 return m.focused
94}
95
96func (m *messageCmp) GetSize() (int, int) {
97 return m.width, 0
98}
99
100func (m *messageCmp) SetSize(width int, height int) {
101 m.width = width
102}
103
104func NewMessageCmp(msg message.Message) MessagesCmp {
105 return &messageCmp{
106 message: msg,
107 }
108}