1package status
2
3import (
4 "time"
5
6 "github.com/charmbracelet/bubbles/v2/help"
7 tea "github.com/charmbracelet/bubbletea/v2"
8 "github.com/charmbracelet/crush/internal/tui/styles"
9 "github.com/charmbracelet/crush/internal/tui/util"
10 "github.com/charmbracelet/x/ansi"
11)
12
13type StatusCmp interface {
14 util.Model
15 ToggleFullHelp()
16 SetKeyMap(keyMap help.KeyMap)
17}
18
19type statusCmp struct {
20 info util.InfoMsg
21 width int
22 messageTTL time.Duration
23 help help.Model
24 keyMap help.KeyMap
25}
26
27// clearMessageCmd is a command that clears status messages after a timeout
28func (m *statusCmp) clearMessageCmd(ttl time.Duration) tea.Cmd {
29 return tea.Tick(ttl, func(time.Time) tea.Msg {
30 return util.ClearStatusMsg{}
31 })
32}
33
34func (m *statusCmp) Init() tea.Cmd {
35 return nil
36}
37
38func (m *statusCmp) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
39 switch msg := msg.(type) {
40 case tea.WindowSizeMsg:
41 m.width = msg.Width
42 m.help.Width = msg.Width - 2
43 return m, nil
44
45 // Handle status info
46 case util.InfoMsg:
47 m.info = msg
48 ttl := msg.TTL
49 if ttl == 0 {
50 ttl = m.messageTTL
51 }
52 return m, m.clearMessageCmd(ttl)
53 case util.ClearStatusMsg:
54 m.info = util.InfoMsg{}
55 }
56 return m, nil
57}
58
59func (m *statusCmp) View() string {
60 t := styles.CurrentTheme()
61 status := t.S().Base.Padding(0, 1, 1, 1).Render(m.help.View(m.keyMap))
62 if m.info.Msg != "" {
63 status = m.infoMsg()
64 }
65 return status
66}
67
68func (m *statusCmp) infoMsg() string {
69 t := styles.CurrentTheme()
70 message := ""
71 infoType := ""
72 switch m.info.Type {
73 case util.InfoTypeError:
74 infoType = t.S().Base.Background(t.Red).Padding(0, 1).Render("ERROR")
75 message = t.S().Base.Background(t.Error).Foreground(t.White).Padding(0, 1).Render(m.info.Msg)
76 case util.InfoTypeWarn:
77 infoType = t.S().Base.Foreground(t.BgOverlay).Background(t.Yellow).Padding(0, 1).Render("WARNING")
78 message = t.S().Base.Foreground(t.BgOverlay).Background(t.Warning).Padding(0, 1).Render(m.info.Msg)
79 default:
80 infoType = t.S().Base.Foreground(t.BgOverlay).Background(t.Green).Padding(0, 1).Render("OKAY!")
81 message = t.S().Base.Background(t.Success).Foreground(t.White).Padding(0, 1).Render(m.info.Msg)
82 }
83 return ansi.Truncate(infoType+message, m.width, "…")
84}
85
86func (m *statusCmp) ToggleFullHelp() {
87 m.help.ShowAll = !m.help.ShowAll
88}
89
90func (m *statusCmp) SetKeyMap(keyMap help.KeyMap) {
91 m.keyMap = keyMap
92}
93
94func NewStatusCmp() StatusCmp {
95 t := styles.CurrentTheme()
96 help := help.New()
97 help.Styles = t.S().Help
98 return &statusCmp{
99 messageTTL: 5 * time.Second,
100 help: help,
101 }
102}