diff --git a/internal/ui/model.go b/internal/ui/model.go index 70c966f..5ea280b 100644 --- a/internal/ui/model.go +++ b/internal/ui/model.go @@ -1761,6 +1761,12 @@ func (m *Model) scrollMain(delta int) { m.textTop = clamp(m.textTop+delta, 0, maxi(0, len(m.textLines)-(m.layout().midH-2))) return } + if m.mode == modeShell { + // The pane shows the shell, so the table behind it is not what the + // wheel is over. Falling through moved its selection, and detaching + // then landed on a different row. + return + } _, rows := m.tableData() m.rowIdx = clamp(m.rowIdx+delta, 0, maxi(0, len(rows)-1)) m.rowMem[m.curKind().Key] = m.rowIdx diff --git a/internal/ui/shell_test.go b/internal/ui/shell_test.go index c07e772..5bc71bf 100644 --- a/internal/ui/shell_test.go +++ b/internal/ui/shell_test.go @@ -212,6 +212,26 @@ func TestShellSizedToThePanel(t *testing.T) { } } +// The table is hidden behind the shell, so the wheel over the pane must not +// move its selection: detaching would land on a different row. +func TestWheelOverTheShellLeavesTheTableAlone(t *testing.T) { + m, sh := newShellModel(t) + openShell(t, m, sh) + kind := m.curKind().Key + rowBefore, memBefore := m.rowIdx, m.rowMem[kind] + + l := m.layout() + m.handleMouse(wheel(l.leftW+5, l.midY+4, false)) + m.handleMouse(wheel(l.leftW+5, l.midY+4, false)) + + if m.rowIdx != rowBefore || m.rowMem[kind] != memBefore { + t.Errorf("wheel over the shell moved the table: row %d -> %d", rowBefore, m.rowIdx) + } + if m.mode != modeShell { + t.Errorf("mode = %v, want the shell to stay open", m.mode) + } +} + func TestNoShellFallsBackToAToast(t *testing.T) { m := newTestModel(t, mock.New("")) // demo backend has no shell dismissOnboarding(m)