@@ -82,7 +82,7 @@ type UI struct {
82 keyenh tea.KeyboardEnhancementsMsg
82 keyenh tea.KeyboardEnhancementsMsg
84 dialog *dialog.Overlay
84 dialog *dialog.Overlay
85− help help.Model
85+ status *Status
87 // header is the last cached header logo
87 // header is the last cached header logo
88 header string
88 header string
@@ -137,13 +137,14 @@ func New(com *common.Common) *UI {
137 com: com,
137 com: com,
138 dialog: dialog.NewOverlay(),
138 dialog: dialog.NewOverlay(),
139 keyMap: DefaultKeyMap(),
139 keyMap: DefaultKeyMap(),
141 focus: uiFocusNone,
140 focus: uiFocusNone,
142 state: uiConfigure,
141 state: uiConfigure,
143 textarea: ta,
142 textarea: ta,
144 chat: ch,
143 chat: ch,
146+ status := NewStatus(com, ui)
147 // set onboarding state defaults
148 // set onboarding state defaults
148 ui.onboarding.yesInitializeSelected = true
149 ui.onboarding.yesInitializeSelected = true
@@ -162,7 +163,7 @@ func New(com *common.Common) *UI {
162 ui.setEditorPrompt(false)
163 ui.setEditorPrompt(false)
163 ui.randomizePlaceholders()
164 ui.randomizePlaceholders()
164 ui.textarea.Placeholder = ui.readyPlaceholder
165 ui.textarea.Placeholder = ui.readyPlaceholder
165− ui.help.Styles = com.Styles.Help
166+ ui.status = status
167 return ui
168 return ui
@@ -338,6 +339,15 @@ func (m *UI) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
338 case openEditorMsg:
339 case openEditorMsg:
339 m.textarea.SetValue(msg.Text)
340 m.textarea.SetValue(msg.Text)
340 m.textarea.MoveToEnd()
341 m.textarea.MoveToEnd()
342+ case uiutil.InfoMsg:
343+ m.status.SetInfoMsg(msg)
346+ ttl = DefaultStatusTTL
348+ cmds = append(cmds, clearInfoMsgCmd(ttl))
349+ case uiutil.ClearStatusMsg:
350+ m.status.ClearInfoMsg()
343 // This logic gets triggered on any message type, but should it?
353 // This logic gets triggered on any message type, but should it?
@@ -480,7 +490,7 @@ func (m *UI) handleKeyPressMsg(msg tea.KeyPressMsg) tea.Cmd {
480 handleGlobalKeys := func(msg tea.KeyPressMsg) bool {
490 handleGlobalKeys := func(msg tea.KeyPressMsg) bool {
482 case key.Matches(msg, m.keyMap.Help):
492 case key.Matches(msg, m.keyMap.Help):
483− m.help.ShowAll = !m.help.ShowAll
493+ m.status.ToggleHelp()
484 m.updateLayoutAndSize()
494 m.updateLayoutAndSize()
485 return true
495 return true
486 case key.Matches(msg, m.keyMap.Commands):
496 case key.Matches(msg, m.keyMap.Commands):
@@ -569,7 +579,7 @@ func (m *UI) handleKeyPressMsg(msg tea.KeyPressMsg) tea.Cmd {
569 cmds = append(cmds, uiutil.ReportError(err))
579 cmds = append(cmds, uiutil.ReportError(err))
571 case dialog.ToggleHelpMsg:
581 case dialog.ToggleHelpMsg:
572− m.help.ShowAll = !m.help.ShowAll
582+ m.status.ToggleHelp()
573 m.dialog.CloseDialog(dialog.CommandsID)
583 m.dialog.CloseDialog(dialog.CommandsID)
574 case dialog.QuitMsg:
584 case dialog.QuitMsg:
575 cmds = append(cmds, tea.Quit)
585 cmds = append(cmds, tea.Quit)
@@ -815,9 +825,8 @@ func (m *UI) Draw(scr uv.Screen, area uv.Rectangle) {
815 editor.Draw(scr, layout.editor)
825 editor.Draw(scr, layout.editor)
818− // Add help layer
828+ // Add status and help layer
819− help := uv.NewStyledString(m.help.View(m))
820− help.Draw(scr, layout.help)
829+ m.status.Draw(scr, layout.status)
822 // Debugging rendering (visually see when the tui rerenders)
831 // Debugging rendering (visually see when the tui rerenders)
823 if os.Getenv("CRUSH_UI_DEBUG") == "true" {
832 if os.Getenv("CRUSH_UI_DEBUG") == "true" {
@@ -1077,8 +1086,8 @@ func (m *UI) updateLayoutAndSize() {
1078// updateSize updates the sizes of UI components based on the current layout.
1087// updateSize updates the sizes of UI components based on the current layout.
1079func (m *UI) updateSize() {
1088func (m *UI) updateSize() {
1080− // Set help width
1089+ // Set status width
1081− m.help.SetWidth(m.layout.help.Dx())
1090+ m.status.SetWidth(m.layout.status.Dx())
1083 m.chat.SetSize(m.layout.main.Dx(), m.layout.main.Dy())
1092 m.chat.SetSize(m.layout.main.Dx(), m.layout.main.Dy())
1084 m.textarea.SetWidth(m.layout.editor.Dx())
1093 m.textarea.SetWidth(m.layout.editor.Dx())
@@ -1115,18 +1124,16 @@ func (m *UI) generateLayout(w, h int) layout {
1115 headerHeight := 4
1124 headerHeight := 4
1117 var helpKeyMap help.KeyMap = m
1126 var helpKeyMap help.KeyMap = m
1118− if m.help.ShowAll {
1127+ if m.status.ShowingAll() {
1119 for _, row := range helpKeyMap.FullHelp() {
1128 for _, row := range helpKeyMap.FullHelp() {
1120 helpHeight = max(helpHeight, len(row))
1129 helpHeight = max(helpHeight, len(row))
1124 // Add app margins
1133 // Add app margins
1125− appRect := area
1134+ appRect, helpRect := uv.SplitVertical(area, uv.Fixed(area.Dy()-helpHeight))
1126 appRect.Min.X += 1
1135 appRect.Min.X += 1
1128 appRect.Max.X -= 1
1136 appRect.Max.X -= 1
1131 if slices.Contains([]uiState{uiConfigure, uiInitialize, uiLanding}, m.state) {
1138 if slices.Contains([]uiState{uiConfigure, uiInitialize, uiLanding}, m.state) {
1132 // extra padding on left and right for these states
1139 // extra padding on left and right for these states
@@ -1134,11 +1141,9 @@ func (m *UI) generateLayout(w, h int) layout {
1134 appRect.Max.X -= 1
1141 appRect.Max.X -= 1
1137− appRect, helpRect := uv.SplitVertical(appRect, uv.Fixed(appRect.Dy()-helpHeight))
1139 layout := layout{
1144 layout := layout{
1140− area: area,
1145+ area: area,
1141− help: helpRect,
1146+ status: helpRect,
1144 // Handle different app states
1149 // Handle different app states
@@ -1242,8 +1247,8 @@ type layout struct {
1242 // sidebar is the area for the sidebar.
1247 // sidebar is the area for the sidebar.
1243 sidebar uv.Rectangle
1248 sidebar uv.Rectangle
1245− // help is the area for the help view.
1250+ // status is the area for the status view.
1246− help uv.Rectangle
1251+ status uv.Rectangle
1249func (m *UI) openEditor(value string) tea.Cmd {
1254func (m *UI) openEditor(value string) tea.Cmd {