SuperCoder/internal/tui/components/core/status.go

103 lines
2.7 KiB
Go
Raw Normal View History

2025-03-23 14:56:32 +01:00
package core
import (
"time"
2025-03-23 14:56:32 +01:00
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
2025-03-27 22:35:48 +01:00
"github.com/kujtimiihoxha/termai/internal/config"
"github.com/kujtimiihoxha/termai/internal/llm/models"
2025-03-23 14:56:32 +01:00
"github.com/kujtimiihoxha/termai/internal/tui/styles"
"github.com/kujtimiihoxha/termai/internal/tui/util"
"github.com/kujtimiihoxha/termai/internal/version"
)
type statusCmp struct {
2025-04-10 13:29:44 +02:00
info util.InfoMsg
2025-04-07 19:43:31 +02:00
width int
messageTTL time.Duration
}
// clearMessageCmd is a command that clears status messages after a timeout
2025-04-09 19:07:39 +02:00
func (m statusCmp) clearMessageCmd(ttl time.Duration) tea.Cmd {
return tea.Tick(ttl, func(time.Time) tea.Msg {
return util.ClearStatusMsg{}
})
2025-03-23 14:56:32 +01:00
}
func (m statusCmp) Init() tea.Cmd {
return nil
}
func (m statusCmp) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {
case tea.WindowSizeMsg:
m.width = msg.Width
2025-04-09 19:07:39 +02:00
return m, nil
2025-03-23 14:56:32 +01:00
case util.InfoMsg:
2025-04-10 13:29:44 +02:00
m.info = msg
2025-04-09 19:07:39 +02:00
ttl := msg.TTL
if ttl == 0 {
ttl = m.messageTTL
}
return m, m.clearMessageCmd(ttl)
case util.ClearStatusMsg:
2025-04-10 13:29:44 +02:00
m.info = util.InfoMsg{}
2025-03-23 14:56:32 +01:00
}
return m, nil
}
var (
versionWidget = styles.Padded.Background(styles.DarkGrey).Foreground(styles.Text).Render(version.Version)
helpWidget = styles.Padded.Background(styles.Grey).Foreground(styles.Text).Render("? help")
)
func (m statusCmp) View() string {
status := styles.Padded.Background(styles.Grey).Foreground(styles.Text).Render("? help")
2025-04-10 13:29:44 +02:00
if m.info.Msg != "" {
2025-04-07 19:43:31 +02:00
infoStyle := styles.Padded.
2025-03-23 14:56:32 +01:00
Foreground(styles.Base).
2025-04-07 19:43:31 +02:00
Width(m.availableFooterMsgWidth())
switch m.info.Type {
case util.InfoTypeInfo:
infoStyle = infoStyle.Background(styles.Blue)
case util.InfoTypeWarn:
infoStyle = infoStyle.Background(styles.Peach)
case util.InfoTypeError:
infoStyle = infoStyle.Background(styles.Red)
}
2025-04-09 19:07:39 +02:00
// Truncate message if it's longer than available width
msg := m.info.Msg
2025-04-09 20:04:44 +02:00
availWidth := m.availableFooterMsgWidth() - 10
2025-04-09 19:07:39 +02:00
if len(msg) > availWidth && availWidth > 0 {
msg = msg[:availWidth] + "..."
}
status += infoStyle.Render(msg)
2025-03-23 14:56:32 +01:00
} else {
status += styles.Padded.
Foreground(styles.Base).
Background(styles.LightGrey).
Width(m.availableFooterMsgWidth()).
2025-04-07 19:43:31 +02:00
Render("")
2025-03-23 14:56:32 +01:00
}
2025-03-27 22:35:48 +01:00
status += m.model()
2025-03-23 14:56:32 +01:00
status += versionWidget
return status
}
func (m statusCmp) availableFooterMsgWidth() int {
// -2 to accommodate padding
2025-03-27 22:35:48 +01:00
return max(0, m.width-lipgloss.Width(helpWidget)-lipgloss.Width(versionWidget)-lipgloss.Width(m.model()))
}
func (m statusCmp) model() string {
model := models.SupportedModels[config.Get().Model.Coder]
return styles.Padded.Background(styles.Grey).Foreground(styles.Text).Render(model.Name)
2025-03-23 14:56:32 +01:00
}
func NewStatusCmp() tea.Model {
return &statusCmp{
2025-04-09 19:18:51 +02:00
messageTTL: 10 * time.Second,
}
2025-03-23 14:56:32 +01:00
}