f89ca8acb9
Three layout improvements for better space utilization: - Compact date headers: date labels render as left gutter column instead of standalone lines, saving one line per date group in stream view - Input drawer: capture bar expands to 4-line drawer with border, hints, and live preview of parsed entity/search query - Split-pane detail: wide terminals (>=100 cols) show list and detail side-by-side with h/l focus switching, falling back to full-screen detail on narrow terminals
72 lines
1.7 KiB
Go
72 lines
1.7 KiB
Go
package tui
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/charmbracelet/lipgloss"
|
|
)
|
|
|
|
func renderStatusBar(m model, width int) string {
|
|
left := countText(m)
|
|
right := contextHints(m)
|
|
|
|
leftRendered := statusStyle.Render(left)
|
|
rightRendered := helpStyle.Render(right)
|
|
|
|
gap := width - lipgloss.Width(leftRendered) - lipgloss.Width(rightRendered)
|
|
if gap < 0 {
|
|
gap = 0
|
|
}
|
|
|
|
pad := lipgloss.NewStyle().Width(gap).Render("")
|
|
return leftRendered + pad + rightRendered
|
|
}
|
|
|
|
func countText(m model) string {
|
|
var total int
|
|
if m.mode == modeCards {
|
|
total = len(m.cards.filtered)
|
|
} else {
|
|
total = len(m.list.displayEntities())
|
|
}
|
|
if m.filterTag != "" {
|
|
return fmt.Sprintf("%d entities #%s", total, m.filterTag)
|
|
}
|
|
return fmt.Sprintf("%d entities", total)
|
|
}
|
|
|
|
func contextHints(m model) string {
|
|
switch m.state {
|
|
case stateDetail:
|
|
switch m.detail.mode {
|
|
case detailRun:
|
|
return "space:toggle j/k:nav r:reset esc:save+exit"
|
|
case detailFill:
|
|
return "tab:next shift+tab:prev enter:copy esc:cancel"
|
|
default:
|
|
return "p:promote D:demote c:copy e:edit r:run f:fill !:pin esc:back"
|
|
}
|
|
case stateInput:
|
|
return ""
|
|
case stateTagFilter:
|
|
return "j/k:nav enter:select esc:cancel"
|
|
case stateConfirm:
|
|
return "y:confirm n:cancel"
|
|
case statePromote:
|
|
return "j/k:nav enter:select esc:cancel"
|
|
case stateAbsorb:
|
|
return "j/k:nav enter:absorb esc:cancel"
|
|
default:
|
|
if m.splitDetail {
|
|
if m.focus == focusDetail {
|
|
return "h:list c:copy e:edit p:promote D:demote !:pin esc:back"
|
|
}
|
|
return "l:detail a:add d:del #:filter esc:close ?:help q:quit"
|
|
}
|
|
if m.mode == modeCards {
|
|
return "1:stream 2:cards s:sort tab:intent a:add ?:help q:quit"
|
|
}
|
|
return "1:stream 2:cards a:add/?search m:absorb d:del #:filter ?:help q:quit"
|
|
}
|
|
}
|