message.go

  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}