diff options
| author | Lukasz Kasprzak <lukas@labunix.xyz> | 2026-07-29 13:55:27 +0200 |
|---|---|---|
| committer | Lukasz Kasprzak <lukas@labunix.xyz> | 2026-07-29 13:55:27 +0200 |
| commit | 18578434f41d4fe34438c2f171388109a288c18c (patch) | |
| tree | ffeb1108c564840be530f4a6006aa9acb222a412 /internal/tui/reader.go | |
| parent | 6964ee56de01f9769a39ba480dc787339b642f7a (diff) | |
| download | lectio-18578434f41d4fe34438c2f171388109a288c18c.tar.gz lectio-18578434f41d4fe34438c2f171388109a288c18c.zip | |
tui(reader): flag bookmarked verses with a red * in the reading pane
A verse that has a bookmark now shows a red "*" at the end of its last line, so
saved verses are visible while reading. The set of bookmarked verses for the
current book+chapter is refreshed on chapter load, on save, and on returning
from the bookmarks list (one store read each). Test covers the flag + render.
Diffstat (limited to 'internal/tui/reader.go')
| -rw-r--r-- | internal/tui/reader.go | 48 |
1 files changed, 41 insertions, 7 deletions
diff --git a/internal/tui/reader.go b/internal/tui/reader.go index de89a40..973161d 100644 --- a/internal/tui/reader.go +++ b/internal/tui/reader.go @@ -33,6 +33,9 @@ const ( // selStyle marks the picker's selected row (reverse video, legible on any theme). var selStyle = lipgloss.NewStyle().Reverse(true) +// markStyle renders the red "*" that flags a verse carrying a bookmark. +var markStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("1")).Bold(true) + // modalStyle / modalTitleStyle render the bookmark note box and the delete // confirmation as a prominent centered, bordered dialog (not a footer line). var ( @@ -92,6 +95,7 @@ type ReaderModel struct { markFilter string // active tag filter (substring, case-insensitive) markFiltering bool // typing into the tag filter confirmDelete bool // bookmarks list is awaiting delete confirmation + markedVerses map[int]bool // verse numbers in the current book+chapter that carry a bookmark flash string // transient status line (e.g. "bookmarked ...") width, height int @@ -488,7 +492,7 @@ func (m ReaderModel) updateBookmarks(msg tea.KeyMsg) (tea.Model, tea.Cmd) { return m, nil } m.mode = modeRead - return m, nil + return m.withMarks(), nil case "/": m.markFiltering = true return m, nil @@ -689,6 +693,30 @@ func (m ReaderModel) scrollToVerse(verse int) int { // saveBookmark stores a bookmark of the current book+chapter at the chosen // verse with an optional note, and sets a flash message. +// withMarks recomputes the set of verse numbers in the current book+chapter that +// carry a bookmark, so the reader can flag them with a red "*". One store read; +// refreshed on chapter load, on save, and on returning from the bookmarks list. +func (m ReaderModel) withMarks() ReaderModel { + m.markedVerses = nil + if m.store == nil || m.bookIdx < 0 || m.bookIdx >= len(m.books) { + return m + } + all, err := m.store.List("") + if err != nil { + return m + } + canon := m.books[m.bookIdx].Canonical + chap := m.currentChapter() + set := map[int]bool{} + for _, bm := range all { + if bm.Book == canon && bm.Chapter == chap { + set[bm.Verse] = true + } + } + m.markedVerses = set + return m +} + func (m ReaderModel) saveBookmark(verse int, note, tags string) ReaderModel { if m.store == nil || len(m.verses) == 0 { return m @@ -706,7 +734,7 @@ func (m ReaderModel) saveBookmark(verse int, note, tags string) ReaderModel { Tags: bookmarks.ParseTags(tags), }) m.flash = fmt.Sprintf("bookmarked %s %d:%d", book.Name, chap, verse) - return m + return m.withMarks() } // savePlace persists the current reading position (book+chapter+top verse) so @@ -752,7 +780,7 @@ func (m ReaderModel) openBook() ReaderModel { func (m ReaderModel) loadVerses() ReaderModel { if len(m.chapters) == 0 { m.verses = nil - return m + return m.withMarks() } if m.chapPos < 0 { m.chapPos = 0 @@ -761,7 +789,7 @@ func (m ReaderModel) loadVerses() ReaderModel { m.chapPos = len(m.chapters) - 1 } m.verses = bible.Verses(m.version(), m.books[m.bookIdx].Canonical, m.chapters[m.chapPos]) - return m + return m.withMarks() } func (m ReaderModel) chapterStep(d int) ReaderModel { @@ -850,13 +878,19 @@ func (m ReaderModel) readBodyHL(w, hl int) []string { numW := maxNumWidth(blocks) var lines []string for i, b := range blocks { + var vlines []string if i == hl { for _, ln := range strings.Split(render.Wrap(b, w), "\n") { - lines = append(lines, selStyle.Render(ln)) + vlines = append(vlines, selStyle.Render(ln)) } - continue + } else { + vlines = styleBlock(b, false, w, numW) + } + // Flag a bookmarked verse with a red "*" at the end of its last line. + if m.markedVerses[m.verses[i].Verse] && len(vlines) > 0 { + vlines[len(vlines)-1] += markStyle.Render("*") } - lines = append(lines, styleBlock(b, false, w, numW)...) + lines = append(lines, vlines...) } return lines } |
