status.go

  1package model
  2
  3import (
  4	"time"
  5
  6	"charm.land/bubbles/v2/help"
  7	tea "charm.land/bubbletea/v2"
  8	"charm.land/lipgloss/v2"
  9	"github.com/charmbracelet/crush/internal/ui/common"
 10	"github.com/charmbracelet/crush/internal/uiutil"
 11	uv "github.com/charmbracelet/ultraviolet"
 12	"github.com/charmbracelet/x/ansi"
 13)
 14
 15// DefaultStatusTTL is the default time-to-live for status messages.
 16const DefaultStatusTTL = 5 * time.Second
 17
 18// Status is the status bar and help model.
 19type Status struct {
 20	com    *common.Common
 21	help   help.Model
 22	helpKm help.KeyMap
 23	msg    uiutil.InfoMsg
 24}
 25
 26// NewStatus creates a new status bar and help model.
 27func NewStatus(com *common.Common, km help.KeyMap) *Status {
 28	s := new(Status)
 29	s.com = com
 30	s.help = help.New()
 31	s.help.Styles = com.Styles.Help
 32	s.helpKm = km
 33	return s
 34}
 35
 36// SetInfoMsg sets the status info message.
 37func (s *Status) SetInfoMsg(msg uiutil.InfoMsg) {
 38	s.msg = msg
 39}
 40
 41// ClearInfoMsg clears the status info message.
 42func (s *Status) ClearInfoMsg() {
 43	s.msg = uiutil.InfoMsg{}
 44}
 45
 46// SetWidth sets the width of the status bar and help view.
 47func (s *Status) SetWidth(width int) {
 48	s.help.SetWidth(width)
 49}
 50
 51// ShowingAll returns whether the full help view is shown.
 52func (s *Status) ShowingAll() bool {
 53	return s.help.ShowAll
 54}
 55
 56// ToggleHelp toggles the full help view.
 57func (s *Status) ToggleHelp() {
 58	s.help.ShowAll = !s.help.ShowAll
 59}
 60
 61// Draw draws the status bar onto the screen.
 62func (s *Status) Draw(scr uv.Screen, area uv.Rectangle) {
 63	helpView := s.com.Styles.Status.Help.Render(s.help.View(s.helpKm))
 64	uv.NewStyledString(helpView).Draw(scr, area)
 65
 66	// Render notifications
 67	if s.msg.IsEmpty() {
 68		return
 69	}
 70
 71	var indStyle lipgloss.Style
 72	var msgStyle lipgloss.Style
 73	switch s.msg.Type {
 74	case uiutil.InfoTypeError:
 75		indStyle = s.com.Styles.Status.ErrorIndicator
 76		msgStyle = s.com.Styles.Status.ErrorMessage
 77	case uiutil.InfoTypeWarn:
 78		indStyle = s.com.Styles.Status.WarnIndicator
 79		msgStyle = s.com.Styles.Status.WarnMessage
 80	case uiutil.InfoTypeUpdate:
 81		indStyle = s.com.Styles.Status.UpdateIndicator
 82		msgStyle = s.com.Styles.Status.UpdateMessage
 83	case uiutil.InfoTypeInfo:
 84		indStyle = s.com.Styles.Status.InfoIndicator
 85		msgStyle = s.com.Styles.Status.InfoMessage
 86	case uiutil.InfoTypeSuccess:
 87		indStyle = s.com.Styles.Status.SuccessIndicator
 88		msgStyle = s.com.Styles.Status.SuccessMessage
 89	}
 90
 91	ind := indStyle.String()
 92	messageWidth := area.Dx() - lipgloss.Width(ind)
 93	msg := ansi.Truncate(s.msg.Msg, messageWidth, "…")
 94	info := msgStyle.Width(messageWidth).Render(msg)
 95
 96	// Draw the info message over the help view
 97	uv.NewStyledString(ind+info).Draw(scr, area)
 98}
 99
100// clearInfoMsgCmd returns a command that clears the info message after the
101// given TTL.
102func clearInfoMsgCmd(ttl time.Duration) tea.Cmd {
103	return tea.Tick(ttl, func(time.Time) tea.Msg {
104		return uiutil.ClearStatusMsg{}
105	})
106}