package ui import ( "fmt" "io" "strconv" "strings" "charm.land/bubbles/v2/list" tea "charm.land/bubbletea/v2" "github.com/charmbracelet/x/ansi" zone "github.com/lrstanley/bubblezone/v2" "github.com/anotherhadi/default-creds-tui/internal/creds" ) const cardHeight = 4 func entryUserZoneID(index int) string { return "entry-user-" + strconv.Itoa(index) } func entryPassZoneID(index int) string { return "entry-pass-" + strconv.Itoa(index) } func entryZoneID(index int) string { return "entry-" + strconv.Itoa(index) } func clampToWidth(s string, width int) string { if width <= 0 { return s } return ansi.Truncate(s, width, "…") } type entryDelegate struct{} func (d entryDelegate) Height() int { return cardHeight } func (d entryDelegate) Spacing() int { return 1 } func (d entryDelegate) Update(_ tea.Msg, _ *list.Model) tea.Cmd { return nil } func (d entryDelegate) Render(w io.Writer, m list.Model, index int, item list.Item) { e, ok := item.(creds.Entry) if !ok { return } selected := index == m.Index() width := m.Width() side := unselectedIndentStyle name := nameStyle if selected { side = selectedBorderStyle name = nameSelectedStyle } titleParts := []string{manufacturerStyle.Render(strings.ToUpper(e.Manufacturer))} if e.Version != "" && e.Version != "all" { titleParts = append(titleParts, versionStyle.Render("v"+e.Version)) } line1 := strings.Join(titleParts, subtleStyle.Render(" · ")) line2 := name.Render(e.Name) var chips []string if e.User != "" { chips = append(chips, zone.Mark(entryUserZoneID(index), chipStyle.Render("user: "+e.User))) } if e.Pass != "" { chips = append(chips, zone.Mark(entryPassZoneID(index), chipStyle.Render("pass: "+e.Pass))) } line3 := strings.Join(chips, " ") if line3 == "" { line3 = mutedStyle.Render("(no credentials listed)") } line4 := "" switch { case e.Comment != "": line4 = commentStyle.Render(e.Comment) case len(e.Tags) > 0: line4 = subtleStyle.Render("#" + strings.Join(e.Tags, " #")) } lines := []string{ clampToWidth(side.Render(line1), width), clampToWidth(side.Render(line2), width), clampToWidth(side.Render(line3), width), clampToWidth(side.Render(line4), width), } fmt.Fprint(w, zone.Mark(entryZoneID(index), strings.Join(lines, "\n"))) }