diff options
Diffstat (limited to 'internal/tui')
| -rw-r--r-- | internal/tui/tui.go | 59 |
1 files changed, 37 insertions, 22 deletions
diff --git a/internal/tui/tui.go b/internal/tui/tui.go index a4c14b9..47314b6 100644 --- a/internal/tui/tui.go +++ b/internal/tui/tui.go @@ -120,16 +120,18 @@ func shiftDate(date string, days int) string { } // fetchCmd issues the readings.Load fetch for the model's current date as a -// tea.Cmd, resolving to readingsMsg or errMsg. It is a full-day reader, so -// All is always true; Offline follows cfg.Offline. -func (m Model) fetchCmd() tea.Cmd { +// tea.Cmd, resolving to readingsMsg or errMsg. All follows cfg.All (config's +// gospel-only vs every-part choice); Offline follows cfg.Offline; refresh +// bypasses the cache (the "r" key), matching the CLI's --refresh. +func (m Model) fetchCmd(refresh bool) tea.Cmd { cfg := m.cfg date := m.date return func() tea.Msg { secs, err := readings.Load(cfg, readings.Options{ Date: date, + Refresh: refresh, Offline: cfg.Offline, - All: true, + All: cfg.All, }) if err != nil { return errMsg{err} @@ -140,7 +142,7 @@ func (m Model) fetchCmd() tea.Cmd { // Init issues the first load. func (m Model) Init() tea.Cmd { - return m.fetchCmd() + return m.fetchCmd(false) } // Update handles key input and fetch results. @@ -175,38 +177,33 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { m.date = shiftDate(m.date, -1) m.loading = true m.err = nil - return m, m.fetchCmd() + return m, m.fetchCmd(false) case "right": m.date = shiftDate(m.date, +1) m.loading = true m.err = nil - return m, m.fetchCmd() + return m, m.fetchCmd(false) case "r": m.loading = true m.err = nil - return m, m.fetchCmd() + return m, m.fetchCmd(true) case "j", "down": - m.scroll++ + m.scroll = m.scrollTo(m.scroll + 1) return m, nil case "k", "up": - if m.scroll > 0 { - m.scroll-- - } + m.scroll = m.scrollTo(m.scroll - 1) return m, nil case " ": - m.scroll += pageSize(m.height) + m.scroll = m.scrollTo(m.scroll + pageSize(m.height)) return m, nil case "b": - m.scroll -= pageSize(m.height) - if m.scroll < 0 { - m.scroll = 0 - } + m.scroll = m.scrollTo(m.scroll - pageSize(m.height)) return m, nil case "g": m.scroll = 0 return m, nil case "G": - m.scroll = 1 << 30 // clamped to the last page in View + m.scroll = m.scrollTo(1 << 30) return m, nil } } @@ -239,6 +236,27 @@ func clampScroll(scroll, total, visible int) int { return scroll } +// innerWidth is the reading pane's wrap width: the terminal width minus a +// small margin, with an 80-column fallback before the first WindowSizeMsg. +func (m Model) innerWidth() int { + w := m.width + if w <= 0 { + w = 80 + } + iw := w - 2 + if iw < 20 { + iw = 20 + } + return iw +} + +// scrollTo clamps a target scroll offset to the reading's real length, so the +// view can't scroll past the end -- keeping m.scroll bounded in Update, not +// merely clamped for display in View. +func (m Model) scrollTo(s int) int { + return clampScroll(s, len(m.bodyLines(m.innerWidth())), pageSize(m.height)) +} + // View renders the header (date + active version label), the scrolling // reading, and the footer keybar. func (m Model) View() string { @@ -246,10 +264,7 @@ func (m Model) View() string { if w <= 0 { w = 80 } - innerW := w - 2 - if innerW < 20 { - innerW = 20 - } + innerW := m.innerWidth() header := headerStyle.Width(w).Render(m.headerText()) footer := footerStyle.Width(w).Render(i18n.Get(m.cfg.UILanguage).FooterKeys) |
