feat: mouse wheel scrolling in errors tab
All checks were successful
Release / release (push) Successful in 47s

This commit is contained in:
SW 2026-09-10 13:52:55 +02:00
parent 9991f887b0
commit 4acdfeaa87

View file

@ -132,6 +132,8 @@ type model struct {
width int
height int
err error
errorsScrollOffset int
}
func initialModel(client *sshclient.Client, logPath string) model {
@ -233,6 +235,18 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
m.width = msg.Width
m.height = msg.Height
case tea.MouseMsg:
if m.activeTab == tabErrors {
switch msg.Button {
case tea.MouseButtonWheelUp:
if m.errorsScrollOffset > 0 {
m.errorsScrollOffset--
}
case tea.MouseButtonWheelDown:
m.errorsScrollOffset++
}
}
case tea.KeyMsg:
switch msg.String() {
case "q", "ctrl+c":
@ -240,14 +254,18 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
return m, tea.Quit
case "1":
m.activeTab = tabLive
m.errorsScrollOffset = 0
case "2":
m.activeTab = tabDay
m.errorsScrollOffset = 0
return m, m.ensureHistory(tabDay)
case "3":
m.activeTab = tabWeek
m.errorsScrollOffset = 0
return m, m.ensureHistory(tabWeek)
case "4":
m.activeTab = tabErrors
m.errorsScrollOffset = 0
return m, m.ensureHistory(tabDay)
}
@ -290,6 +308,7 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
h.stats = msg.agg.ToStats()
h.buckets = msg.agg.ToBuckets(tabBucketSize(msg.tab))
h.errors = msg.agg.RecentErrors(100)
m.errorsScrollOffset = 0
}
case errMsg:
@ -506,8 +525,34 @@ func (m model) renderErrors() string {
ipW, "REMOTE IP",
"URI",
)
// Fixed-height overhead: header + tab bar + title/header rows + footer/borders.
const overhead = 10
maxRows := m.height - overhead
if maxRows < 3 {
maxRows = 3
}
// Clamp scroll offset.
if m.errorsScrollOffset > len(errs)-maxRows {
if len(errs) > maxRows {
m.errorsScrollOffset = len(errs) - maxRows
} else {
m.errorsScrollOffset = 0
}
}
if m.errorsScrollOffset < 0 {
m.errorsScrollOffset = 0
}
end := m.errorsScrollOffset + maxRows
if end > len(errs) {
end = len(errs)
}
visible := errs[m.errorsScrollOffset:end]
rows := []string{styleHeader.Render(title), "", styleHeader.Render(header)}
for _, e := range errs {
for _, e := range visible {
statusStr := fmt.Sprintf("%d", e.Status)
var statusStyled string
if e.Status >= 500 {
@ -732,7 +777,7 @@ func bucketSizeLabel(d time.Duration) string {
// -- entry point --------------------------------------------------------------
func Run(client *sshclient.Client, logPath string) error {
p := tea.NewProgram(initialModel(client, logPath), tea.WithAltScreen())
p := tea.NewProgram(initialModel(client, logPath), tea.WithAltScreen(), tea.WithMouseCellMotion())
_, err := p.Run()
return err
}