package tui import ( "strings" "github.com/lerko/nib/internal/db" "github.com/lerko/nib/internal/link" ) type linkKind int const ( linkOutgoing linkKind = iota linkBacklink ) type linkItem struct { text string entityID string kind linkKind } type linkPickerModel struct { items []linkItem cursor int } func newLinkPicker(body string, backlinks []db.Backlink) linkPickerModel { var items []linkItem for _, lt := range link.ExtractLinks(body) { items = append(items, linkItem{text: lt, kind: linkOutgoing}) } for _, bl := range backlinks { label := bl.Body if bl.Title != nil { label = *bl.Title } else if len(label) > 50 { label = label[:50] + "…" } items = append(items, linkItem{text: label, entityID: bl.EntityID, kind: linkBacklink}) } return linkPickerModel{items: items} } func (lp linkPickerModel) selected() linkItem { if len(lp.items) == 0 || lp.cursor >= len(lp.items) { return linkItem{} } return lp.items[lp.cursor] } func (lp linkPickerModel) update(key string) linkPickerModel { switch key { case "up", "k": if lp.cursor > 0 { lp.cursor-- } case "down", "j": if lp.cursor < len(lp.items)-1 { lp.cursor++ } } return lp } func (lp linkPickerModel) view(width int) string { var b strings.Builder b.WriteString(titleStyle.Render("follow link") + "\n\n") if len(lp.items) == 0 { b.WriteString(hintDescStyle.Render(" no links or backlinks")) b.WriteString("\n\n") b.WriteString(helpStyle.Render("esc:back")) return b.String() } prevKind := linkKind(-1) for i, item := range lp.items { if item.kind != prevKind { if item.kind == linkOutgoing { b.WriteString(dateHeaderStyle.Render("── outgoing ──") + "\n") } else { b.WriteString(dateHeaderStyle.Render("── backlinks ──") + "\n") } prevKind = item.kind } var label string if item.kind == linkOutgoing { label = "[[" + item.text + "]]" } else { label = "← " + item.text } if i == lp.cursor { b.WriteString(selectedItemStyle.Render(" " + label)) } else { b.WriteString(listItemStyle.Render(label)) } b.WriteString("\n") } b.WriteString("\n") b.WriteString(helpStyle.Render("enter:follow esc:back")) return b.String() }