1package core
2
3import (
4 "time"
5
6 tea "github.com/charmbracelet/bubbletea"
7 "github.com/charmbracelet/lipgloss"
8 "github.com/kujtimiihoxha/termai/internal/config"
9 "github.com/kujtimiihoxha/termai/internal/llm/models"
10 "github.com/kujtimiihoxha/termai/internal/tui/styles"
11 "github.com/kujtimiihoxha/termai/internal/tui/util"
12 "github.com/kujtimiihoxha/termai/internal/version"
13)
14
15type statusCmp struct {
16 info *util.InfoMsg
17 width int
18 messageTTL time.Duration
19}
20
21// clearMessageCmd is a command that clears status messages after a timeout
22func (m statusCmp) clearMessageCmd() tea.Cmd {
23 return tea.Tick(m.messageTTL, func(time.Time) tea.Msg {
24 return util.ClearStatusMsg{}
25 })
26}
27
28func (m statusCmp) Init() tea.Cmd {
29 return nil
30}
31
32func (m statusCmp) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
33 switch msg := msg.(type) {
34 case tea.WindowSizeMsg:
35 m.width = msg.Width
36 return m, m.clearMessageCmd()
37 case util.InfoMsg:
38 m.info = &msg
39 return m, m.clearMessageCmd()
40 case util.ClearStatusMsg:
41 m.info = nil
42 }
43 return m, nil
44}
45
46var (
47 versionWidget = styles.Padded.Background(styles.DarkGrey).Foreground(styles.Text).Render(version.Version)
48 helpWidget = styles.Padded.Background(styles.Grey).Foreground(styles.Text).Render("? help")
49)
50
51func (m statusCmp) View() string {
52 status := styles.Padded.Background(styles.Grey).Foreground(styles.Text).Render("? help")
53 if m.info != nil {
54 infoStyle := styles.Padded.
55 Foreground(styles.Base).
56 Width(m.availableFooterMsgWidth())
57 switch m.info.Type {
58 case util.InfoTypeInfo:
59 infoStyle = infoStyle.Background(styles.Blue)
60 case util.InfoTypeWarn:
61 infoStyle = infoStyle.Background(styles.Peach)
62 case util.InfoTypeError:
63 infoStyle = infoStyle.Background(styles.Red)
64 }
65 status += infoStyle.Render(m.info.Msg)
66 } else {
67 status += styles.Padded.
68 Foreground(styles.Base).
69 Background(styles.LightGrey).
70 Width(m.availableFooterMsgWidth()).
71 Render("")
72 }
73 status += m.model()
74 status += versionWidget
75 return status
76}
77
78func (m statusCmp) availableFooterMsgWidth() int {
79 // -2 to accommodate padding
80 return max(0, m.width-lipgloss.Width(helpWidget)-lipgloss.Width(versionWidget)-lipgloss.Width(m.model()))
81}
82
83func (m statusCmp) model() string {
84 model := models.SupportedModels[config.Get().Model.Coder]
85 return styles.Padded.Background(styles.Grey).Foreground(styles.Text).Render(model.Name)
86}
87
88func NewStatusCmp() tea.Model {
89 return &statusCmp{
90 messageTTL: 5 * time.Second,
91 }
92}