Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions internal/tui/help.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ func (m helpOverlayModel) View() string {
content.WriteString(shortcut("b", "Manage blocking") + "\n")
content.WriteString(shortcut("c", "Create new bean") + "\n")
content.WriteString(shortcut("e", "Edit in $EDITOR") + "\n")
content.WriteString(shortcut("H", "Toggle hide completed") + "\n")
content.WriteString(shortcut("p", "Set parent") + "\n")
content.WriteString(shortcut("P", "Change priority") + "\n")
content.WriteString(shortcut("s", "Change status") + "\n")
Expand Down
48 changes: 39 additions & 9 deletions internal/tui/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"fmt"
"io"
"strings"

"github.com/charmbracelet/bubbles/list"
tea "github.com/charmbracelet/bubbletea"
Expand Down Expand Up @@ -115,7 +116,8 @@ type listModel struct {
idColWidth int // ID column width (accounts for tree depth)

// Active filters
tagFilter string // if set, only show beans with this tag
tagFilter string // if set, only show beans with this tag
hideCompleted bool // if true, hide completed and scrapped beans

// Multi-select state
selectedBeans map[string]bool // IDs of beans marked for multi-edit
Expand Down Expand Up @@ -167,10 +169,16 @@ func (m listModel) Init() tea.Cmd {
}

func (m listModel) loadBeans() tea.Msg {
// Build filter if tag filter is set
// Build filter based on active filters
var filter *model.BeanFilter
if m.tagFilter != "" {
filter = &model.BeanFilter{Tags: []string{m.tagFilter}}
if m.tagFilter != "" || m.hideCompleted {
filter = &model.BeanFilter{}
if m.tagFilter != "" {
filter.Tags = []string{m.tagFilter}
}
if m.hideCompleted {
filter.ExcludeStatus = []string{"completed", "scrapped"}
}
}

// Query filtered beans
Expand Down Expand Up @@ -216,6 +224,11 @@ func (m *listModel) setTagFilter(tag string) {
m.tagFilter = tag
}

// toggleHideCompleted toggles the hideCompleted filter
func (m *listModel) toggleHideCompleted() {
m.hideCompleted = !m.hideCompleted
}

// clearFilter clears all active filters
func (m *listModel) clearFilter() {
m.tagFilter = ""
Expand Down Expand Up @@ -417,6 +430,10 @@ func (m listModel) Update(msg tea.Msg) (listModel, tea.Cmd) {
}
}
}
case "H":
// Toggle hide completed/scrapped beans
m.toggleHideCompleted()
return m, m.loadBeans
case "y":
// Copy bean ID(s) to clipboard
if len(m.selectedBeans) > 0 {
Expand Down Expand Up @@ -490,9 +507,16 @@ func (m listModel) View() string {
return "Loading..."
}

// Update title based on active filter
// Update title based on active filters
var titleParts []string
if m.tagFilter != "" {
m.list.Title = fmt.Sprintf("Beans [tag: %s]", m.tagFilter)
titleParts = append(titleParts, fmt.Sprintf("tag: %s", m.tagFilter))
}
if m.hideCompleted {
titleParts = append(titleParts, "hiding completed")
}
if len(titleParts) > 0 {
m.list.Title = fmt.Sprintf("Beans [%s]", strings.Join(titleParts, "] ["))
} else {
m.list.Title = "Beans"
}
Expand Down Expand Up @@ -592,13 +616,19 @@ func (m listModel) ViewConstrained(width, height int) string {
m.cols = ui.CalculateResponsiveColumns(width, m.hasTags)
m.updateDelegate()

// Update title based on active filter
// Update title based on active filters
var titleParts []string
if m.tagFilter != "" {
m.list.Title = fmt.Sprintf("Beans [tag: %s]", m.tagFilter)
titleParts = append(titleParts, fmt.Sprintf("tag: %s", m.tagFilter))
}
if m.hideCompleted {
titleParts = append(titleParts, "hiding completed")
}
if len(titleParts) > 0 {
m.list.Title = fmt.Sprintf("Beans [%s]", strings.Join(titleParts, "] ["))
} else {
m.list.Title = "Beans"
}

return m.viewContent(innerHeight)
}