| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109 |
- package status
- import (
- "time"
- "github.com/charmbracelet/bubbles/v2/help"
- tea "github.com/charmbracelet/bubbletea/v2"
- "github.com/charmbracelet/crush/internal/tui/styles"
- "github.com/charmbracelet/crush/internal/tui/util"
- "github.com/charmbracelet/lipgloss/v2"
- "github.com/charmbracelet/x/ansi"
- )
- type StatusCmp interface {
- util.Model
- ToggleFullHelp()
- SetKeyMap(keyMap help.KeyMap)
- }
- type statusCmp struct {
- info util.InfoMsg
- width int
- messageTTL time.Duration
- help help.Model
- keyMap help.KeyMap
- }
- // clearMessageCmd is a command that clears status messages after a timeout
- func (m *statusCmp) clearMessageCmd(ttl time.Duration) tea.Cmd {
- return tea.Tick(ttl, func(time.Time) tea.Msg {
- return util.ClearStatusMsg{}
- })
- }
- func (m *statusCmp) Init() tea.Cmd {
- return nil
- }
- func (m *statusCmp) Update(msg tea.Msg) (util.Model, tea.Cmd) {
- switch msg := msg.(type) {
- case tea.WindowSizeMsg:
- m.width = msg.Width
- m.help.Width = msg.Width - 2
- return m, nil
- // Handle status info
- case util.InfoMsg:
- m.info = msg
- ttl := msg.TTL
- if ttl == 0 {
- ttl = m.messageTTL
- }
- return m, m.clearMessageCmd(ttl)
- case util.ClearStatusMsg:
- m.info = util.InfoMsg{}
- }
- return m, nil
- }
- func (m *statusCmp) View() string {
- t := styles.CurrentTheme()
- status := t.S().Base.Padding(0, 1, 1, 1).Render(m.help.View(m.keyMap))
- if m.info.Msg != "" {
- status = m.infoMsg()
- }
- return status
- }
- func (m *statusCmp) infoMsg() string {
- t := styles.CurrentTheme()
- message := ""
- infoType := ""
- switch m.info.Type {
- case util.InfoTypeError:
- infoType = t.S().Base.Background(t.Red).Padding(0, 1).Render("ERROR")
- widthLeft := m.width - (lipgloss.Width(infoType) + 2)
- info := ansi.Truncate(m.info.Msg, widthLeft, "…")
- message = t.S().Base.Background(t.Error).Width(widthLeft+2).Foreground(t.White).Padding(0, 1).Render(info)
- case util.InfoTypeWarn:
- infoType = t.S().Base.Foreground(t.BgOverlay).Background(t.Yellow).Padding(0, 1).Render("WARNING")
- widthLeft := m.width - (lipgloss.Width(infoType) + 2)
- info := ansi.Truncate(m.info.Msg, widthLeft, "…")
- message = t.S().Base.Foreground(t.BgOverlay).Width(widthLeft+2).Background(t.Warning).Padding(0, 1).Render(info)
- default:
- infoType = t.S().Base.Foreground(t.BgOverlay).Background(t.Green).Padding(0, 1).Render("OKAY!")
- widthLeft := m.width - (lipgloss.Width(infoType) + 2)
- info := ansi.Truncate(m.info.Msg, widthLeft, "…")
- message = t.S().Base.Background(t.Success).Width(widthLeft+2).Foreground(t.White).Padding(0, 1).Render(info)
- }
- return ansi.Truncate(infoType+message, m.width, "…")
- }
- func (m *statusCmp) ToggleFullHelp() {
- m.help.ShowAll = !m.help.ShowAll
- }
- func (m *statusCmp) SetKeyMap(keyMap help.KeyMap) {
- m.keyMap = keyMap
- }
- func NewStatusCmp() StatusCmp {
- t := styles.CurrentTheme()
- help := help.New()
- help.Styles = t.S().Help
- return &statusCmp{
- messageTTL: 5 * time.Second,
- help: help,
- }
- }
|