Files
spilltea/internal/ui/findings/update.go
T
Hadi 385b6e84e0 feat: add GotoTop/Bottom/PrevPage/NextPage navigation keys
- New global keybindings: GotoTop (Home), GotoBottom (G/End), PrevPage ([), NextPage (])
- Wired in history, findings, and intercept update handlers
- Removes duplicate tea.Quit case in intercept/update.go

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-19 13:39:01 +02:00

138 lines
3.0 KiB
Go

package findings
import (
"log"
"charm.land/bubbles/v2/key"
tea "charm.land/bubbletea/v2"
"github.com/anotherhadi/spilltea/internal/keys"
)
func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {
case FindingsLoadedMsg:
if msg.Err != nil {
log.Printf("findings load error: %v", msg.Err)
return m, nil
}
m.findings = msg.Findings
if m.cursor >= len(m.findings) {
m.cursor = max(0, len(m.findings)-1)
}
if len(m.findings) == 0 {
m.pager.Page = 0
m.pager.TotalPages = 0
} else {
m.pager.SetTotalPages(len(m.findings))
}
m.refreshListViewport()
m.refreshBody()
return m, nil
case tea.MouseWheelMsg:
switch msg.Button {
case tea.MouseWheelUp:
m.bodyViewport.SetYOffset(m.bodyViewport.YOffset() - 1)
case tea.MouseWheelDown:
m.bodyViewport.SetYOffset(m.bodyViewport.YOffset() + 1)
}
return m, nil
case tea.KeyPressMsg:
g := keys.Keys.Global
f := keys.Keys.Findings
switch {
case key.Matches(msg, g.Up):
if m.cursor > 0 {
m.cursor--
if m.cursor < m.pager.Page*m.pager.PerPage {
m.pager.PrevPage()
}
m.refreshListViewport()
m.refreshBody()
}
case key.Matches(msg, g.Down):
if m.cursor < len(m.findings)-1 {
m.cursor++
if m.cursor >= (m.pager.Page+1)*m.pager.PerPage {
m.pager.NextPage()
}
m.refreshListViewport()
m.refreshBody()
}
case key.Matches(msg, f.Dismiss):
if len(m.findings) > 0 && m.database != nil {
if err := m.database.DismissFinding(m.findings[m.cursor].ID); err != nil {
log.Printf("dismiss finding: %v", err)
return m, nil
}
return m, RefreshCmd(m.database)
}
case key.Matches(msg, g.ScrollUp):
step := m.bodyViewport.Height() / 2
if step < 1 {
step = 1
}
m.bodyViewport.SetYOffset(m.bodyViewport.YOffset() - step)
case key.Matches(msg, g.ScrollDown):
step := m.bodyViewport.Height() / 2
if step < 1 {
step = 1
}
m.bodyViewport.SetYOffset(m.bodyViewport.YOffset() + step)
case key.Matches(msg, g.GotoTop):
m.cursor = 0
m.pager.Page = 0
m.refreshListViewport()
m.refreshBody()
case key.Matches(msg, g.GotoBottom):
if len(m.findings) > 0 {
m.cursor = len(m.findings) - 1
m.pager.Page = m.pager.TotalPages - 1
m.refreshListViewport()
m.refreshBody()
}
case key.Matches(msg, g.PrevPage):
step := m.pager.PerPage
if step < 1 {
step = 1
}
m.cursor -= step
if m.cursor < 0 {
m.cursor = 0
}
m.pager.Page = m.cursor / m.pager.PerPage
m.refreshListViewport()
m.refreshBody()
case key.Matches(msg, g.NextPage):
step := m.pager.PerPage
if step < 1 {
step = 1
}
m.cursor += step
if m.cursor >= len(m.findings) {
m.cursor = len(m.findings) - 1
if m.cursor < 0 {
m.cursor = 0
}
}
m.pager.Page = m.cursor / m.pager.PerPage
m.refreshListViewport()
m.refreshBody()
case key.Matches(msg, g.Help):
m.help.ShowAll = !m.help.ShowAll
m.recalcSizes()
}
}
return m, nil
}
func (m *Model) refreshListViewport() {
m.listViewport.SetContent(m.renderList())
}