Persist comma-separated list filters per project, toggle with space, and jump by first letter in board and project pickers. Co-authored-by: Cursor <cursoragent@cursor.com>
86 lines
1.9 KiB
Go
86 lines
1.9 KiB
Go
package views
|
|
|
|
import (
|
|
"unicode"
|
|
|
|
"github.com/charmbracelet/bubbles/list"
|
|
|
|
"task/internal/project"
|
|
)
|
|
|
|
// ProjectItem wraps a project for bubbles/list.
|
|
type ProjectItem struct {
|
|
Project project.Project
|
|
Active bool
|
|
}
|
|
|
|
func (i ProjectItem) Title() string {
|
|
if i.Active {
|
|
return i.Project.Name + " *"
|
|
}
|
|
return i.Project.Name
|
|
}
|
|
func (i ProjectItem) Description() string { return i.Project.ID }
|
|
func (i ProjectItem) FilterValue() string { return i.Project.Name }
|
|
|
|
// NewProjectList builds a list of projects.
|
|
func NewProjectList(projects []project.Project, activeID string, width, height int) list.Model {
|
|
items := make([]list.Item, len(projects))
|
|
selected := 0
|
|
for i, p := range projects {
|
|
items[i] = ProjectItem{Project: p, Active: p.ID == activeID}
|
|
if p.ID == activeID {
|
|
selected = i
|
|
}
|
|
}
|
|
|
|
delegate := list.NewDefaultDelegate()
|
|
delegate.ShowDescription = false
|
|
l := list.New(items, delegate, width, height)
|
|
l.Title = "Projects"
|
|
l.SetShowStatusBar(false)
|
|
l.SetShowHelp(false)
|
|
l.SetFilteringEnabled(false)
|
|
l.DisableQuitKeybindings()
|
|
if len(items) > 0 {
|
|
l.Select(selected)
|
|
}
|
|
return l
|
|
}
|
|
|
|
// JumpProjectByLetter cycles to the next project whose name starts with r.
|
|
func JumpProjectByLetter(l *list.Model, r rune) bool {
|
|
r = unicode.ToLower(r)
|
|
items := l.Items()
|
|
n := len(items)
|
|
if n == 0 {
|
|
return false
|
|
}
|
|
start := l.Index()
|
|
for step := 1; step <= n; step++ {
|
|
i := (start + step) % n
|
|
pi, ok := items[i].(ProjectItem)
|
|
if !ok {
|
|
continue
|
|
}
|
|
name := []rune(pi.Project.Name)
|
|
if len(name) == 0 {
|
|
continue
|
|
}
|
|
if unicode.ToLower(name[0]) == r {
|
|
l.Select(i)
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// ProjectsToItems converts projects to list items.
|
|
func ProjectsToItems(projects []project.Project, activeID string) []list.Item {
|
|
items := make([]list.Item, len(projects))
|
|
for i, p := range projects {
|
|
items[i] = ProjectItem{Project: p, Active: p.ID == activeID}
|
|
}
|
|
return items
|
|
}
|