255 lines
5.8 KiB
Go
255 lines
5.8 KiB
Go
package components
|
|
|
|
import (
|
|
"strings"
|
|
|
|
"charm.land/lipgloss/v2"
|
|
"github.com/LazyBachelor/LazyPM/internal/style"
|
|
)
|
|
|
|
type ViewKind int
|
|
|
|
const (
|
|
ViewIssues ViewKind = iota
|
|
ViewKanban
|
|
)
|
|
|
|
const (
|
|
fullHelpKeyWidth = 10
|
|
fullHelpDescWidth = 18
|
|
fullHelpColGap = 4
|
|
maxFullHelpCols = 4
|
|
)
|
|
|
|
type HelpItem struct {
|
|
Key string
|
|
Desc string
|
|
}
|
|
|
|
type HelpBarConfig struct {
|
|
ShortItems []HelpItem
|
|
FullItems []HelpItem
|
|
}
|
|
|
|
type HelpBar struct {
|
|
view ViewKind
|
|
config HelpBarConfig
|
|
showAll bool
|
|
width int
|
|
}
|
|
|
|
func NewHelpBar(view ViewKind) HelpBar {
|
|
return HelpBar{
|
|
view: view,
|
|
config: helpBarConfig(view),
|
|
}
|
|
}
|
|
|
|
func (h *HelpBar) SetWidth(width int) {
|
|
h.width = width
|
|
}
|
|
|
|
func (h HelpBar) View() string {
|
|
if h.width == 0 {
|
|
return ""
|
|
}
|
|
|
|
if h.showAll {
|
|
return h.fullHelp()
|
|
}
|
|
|
|
return h.shortHelp()
|
|
}
|
|
|
|
func (h HelpBar) shortHelp() string {
|
|
items := make([]string, 0, len(h.config.ShortItems))
|
|
for _, item := range h.config.ShortItems {
|
|
items = append(
|
|
items,
|
|
style.HighlightKey(item.Key)+item.Desc+" ",
|
|
)
|
|
}
|
|
|
|
content := lipgloss.JoinHorizontal(lipgloss.Left, items...)
|
|
|
|
return lipgloss.NewStyle().
|
|
Border(lipgloss.Border{Top: "─"}, true, false, false, false).
|
|
BorderForeground(style.SecondaryBorder).
|
|
Padding(0, 1).
|
|
Width(h.width).
|
|
Render(content)
|
|
}
|
|
|
|
func (h HelpBar) fullHelp() string {
|
|
if len(h.config.FullItems) == 0 {
|
|
return ""
|
|
}
|
|
|
|
keyStyle := lipgloss.NewStyle().Width(fullHelpKeyWidth).Align(lipgloss.Right)
|
|
descStyle := lipgloss.NewStyle().Width(fullHelpDescWidth)
|
|
cellStyle := lipgloss.NewStyle().Width(fullHelpKeyWidth + 1 + fullHelpDescWidth)
|
|
|
|
renderItem := func(item HelpItem) string {
|
|
return cellStyle.Render(
|
|
keyStyle.Render(style.HighlightKey(item.Key)) + " " + descStyle.Render(item.Desc),
|
|
)
|
|
}
|
|
|
|
innerWidth := max(h.width-2, 1)
|
|
cellWidth := fullHelpKeyWidth + 1 + fullHelpDescWidth
|
|
cols := fitHelpColumns(innerWidth, cellWidth, fullHelpColGap, maxFullHelpCols)
|
|
rows := (len(h.config.FullItems) + cols - 1) / cols
|
|
gap := strings.Repeat(" ", fullHelpColGap)
|
|
|
|
var result []string
|
|
for r := range rows {
|
|
var cells []string
|
|
for c := range cols {
|
|
if idx := r + c*rows; idx < len(h.config.FullItems) {
|
|
cells = append(cells, renderItem(h.config.FullItems[idx]))
|
|
}
|
|
}
|
|
result = append(result, joinHorizontalWithGap(cells, gap))
|
|
}
|
|
|
|
content := lipgloss.JoinVertical(lipgloss.Left, result...)
|
|
return lipgloss.NewStyle().
|
|
Border(lipgloss.Border{Top: "─"}, true, false, false, false).
|
|
BorderForeground(style.SecondaryBorder).
|
|
Padding(0, 1).
|
|
Width(h.width).
|
|
Render(content)
|
|
}
|
|
|
|
func (h HelpBar) Height() int {
|
|
if h.width == 0 {
|
|
return 0
|
|
}
|
|
|
|
return lipgloss.Height(h.View())
|
|
}
|
|
|
|
func (h HelpBar) IsExpanded() bool {
|
|
return h.showAll
|
|
}
|
|
|
|
func (h *HelpBar) ToggleHelp() {
|
|
h.showAll = !h.showAll
|
|
}
|
|
|
|
func fitHelpColumns(
|
|
availableWidth int,
|
|
cellWidth int,
|
|
gapWidth int,
|
|
maxCols int,
|
|
) int {
|
|
for cols := maxCols; cols >= 1; cols-- {
|
|
neededWidth := cols*cellWidth + (cols-1)*gapWidth
|
|
if neededWidth <= availableWidth {
|
|
return cols
|
|
}
|
|
}
|
|
|
|
return 1
|
|
}
|
|
|
|
func joinHorizontalWithGap(cells []string, gap string) string {
|
|
if len(cells) == 0 {
|
|
return ""
|
|
}
|
|
|
|
parts := make([]string, 0, len(cells)*2-1)
|
|
for i, cell := range cells {
|
|
if i > 0 {
|
|
parts = append(parts, gap)
|
|
}
|
|
parts = append(parts, cell)
|
|
}
|
|
|
|
return lipgloss.JoinHorizontal(lipgloss.Left, parts...)
|
|
}
|
|
|
|
func helpBarConfig(view ViewKind) HelpBarConfig {
|
|
switch view {
|
|
case ViewIssues:
|
|
return HelpBarConfig{
|
|
ShortItems: []HelpItem{
|
|
{Key: "v", Desc: "kanban"},
|
|
{Key: "↑/k", Desc: "up"},
|
|
{Key: "↓/j", Desc: "down"},
|
|
{Key: "/", Desc: "search"},
|
|
{Key: "a", Desc: "add"},
|
|
{Key: "c", Desc: "comment"},
|
|
{Key: "e/d/s/p/t/A/D", Desc: "edit"},
|
|
{Key: "x", Desc: "delete"},
|
|
{Key: "q", Desc: "quit"},
|
|
{Key: "?", Desc: "help"},
|
|
},
|
|
FullItems: []HelpItem{
|
|
{Key: "v", Desc: "kanban"},
|
|
{Key: "↑/k", Desc: "up"},
|
|
{Key: "↓/j", Desc: "down"},
|
|
{Key: "/", Desc: "search"},
|
|
{Key: "a", Desc: "add issue"},
|
|
{Key: "c", Desc: "add comment"},
|
|
{Key: "x", Desc: "delete issue"},
|
|
{Key: "e", Desc: "edit title"},
|
|
{Key: "d", Desc: "edit description"},
|
|
{Key: "s", Desc: "change status"},
|
|
{Key: "p", Desc: "change priority"},
|
|
{Key: "t", Desc: "change type"},
|
|
{Key: "A", Desc: "change assignee"},
|
|
{Key: "D", Desc: "edit dependencies"},
|
|
{Key: "q", Desc: "quit"},
|
|
{Key: "?", Desc: "help"},
|
|
},
|
|
}
|
|
|
|
case ViewKanban:
|
|
return HelpBarConfig{
|
|
ShortItems: []HelpItem{
|
|
{Key: "v", Desc: "list view"},
|
|
{Key: "↑/k", Desc: "up"},
|
|
{Key: "↓/j", Desc: "down"},
|
|
{Key: "/", Desc: "search"},
|
|
{Key: "n", Desc: "new sprint"},
|
|
{Key: "S", Desc: "select sprint"},
|
|
{Key: "pgup/pgdn", Desc: "page"},
|
|
{Key: "←/→", Desc: "column"},
|
|
{Key: "h/l", Desc: "move"},
|
|
{Key: "a", Desc: "add"},
|
|
{Key: "e/d/s/p/t/A/D", Desc: "edit"},
|
|
{Key: "x", Desc: "delete"},
|
|
{Key: "q", Desc: "quit"},
|
|
{Key: "?", Desc: "help"},
|
|
},
|
|
FullItems: []HelpItem{
|
|
{Key: "v", Desc: "list view"},
|
|
{Key: "←/→", Desc: "switch column"},
|
|
{Key: "h/l", Desc: "move issue"},
|
|
{Key: "↑/k", Desc: "up"},
|
|
{Key: "↓/j", Desc: "down"},
|
|
{Key: "/", Desc: "search"},
|
|
{Key: "pgup", Desc: "page up"},
|
|
{Key: "pgdn", Desc: "page down"},
|
|
{Key: "a", Desc: "add issue"},
|
|
{Key: "x", Desc: "delete issue"},
|
|
{Key: "e", Desc: "edit title"},
|
|
{Key: "d", Desc: "edit description"},
|
|
{Key: "s", Desc: "change status"},
|
|
{Key: "p", Desc: "change priority"},
|
|
{Key: "t", Desc: "change type"},
|
|
{Key: "A", Desc: "change assignee"},
|
|
{Key: "D", Desc: "manage dependency"}, // dependencies -> dependency cuz dependencies added a newline
|
|
{Key: "S", Desc: "select sprint"},
|
|
{Key: "n", Desc: "new sprint"},
|
|
{Key: "q", Desc: "quit"},
|
|
{Key: "?", Desc: "help"},
|
|
},
|
|
}
|
|
|
|
default:
|
|
return HelpBarConfig{}
|
|
}
|
|
}
|