mirror of
https://github.com/aljazceru/opencode.git
synced 2026-01-10 11:24:59 +01:00
Feat: Implement Wrap-Around Navigation for List Selection (for Models and Tools modal) (#1768)
This commit is contained in:
committed by
GitHub
parent
23757f3ac0
commit
ab2df0ae33
@@ -173,7 +173,13 @@ func (c *listComponent[T]) moveUp() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If no selectable item found above, stay at current position
|
// If no selectable item found above, wrap to the bottom
|
||||||
|
for i := len(c.items) - 1; i > c.selectedIdx; i-- {
|
||||||
|
if c.isSelectable(c.items[i]) {
|
||||||
|
c.selectedIdx = i
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// moveDown moves the selection down, skipping non-selectable items
|
// moveDown moves the selection down, skipping non-selectable items
|
||||||
@@ -183,20 +189,19 @@ func (c *listComponent[T]) moveDown() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
originalIdx := c.selectedIdx
|
originalIdx := c.selectedIdx
|
||||||
for {
|
// First try moving down from current position
|
||||||
if c.selectedIdx < len(c.items)-1 {
|
for i := c.selectedIdx + 1; i < len(c.items); i++ {
|
||||||
c.selectedIdx++
|
if c.isSelectable(c.items[i]) {
|
||||||
} else {
|
c.selectedIdx = i
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.isSelectable(c.items[c.selectedIdx]) {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Prevent infinite loop
|
// If no selectable item found below, wrap to the top
|
||||||
if c.selectedIdx == originalIdx {
|
for i := 0; i < originalIdx; i++ {
|
||||||
break
|
if c.isSelectable(c.items[i]) {
|
||||||
|
c.selectedIdx = i
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -138,15 +138,18 @@ func TestCtrlNavigation(t *testing.T) {
|
|||||||
func TestNavigationBoundaries(t *testing.T) {
|
func TestNavigationBoundaries(t *testing.T) {
|
||||||
list := createTestList()
|
list := createTestList()
|
||||||
|
|
||||||
// Test up arrow at first item (should stay at 0)
|
// Test up arrow at first item (should wrap to last item)
|
||||||
upKey := tea.KeyPressMsg{Code: tea.KeyUp}
|
upKey := tea.KeyPressMsg{Code: tea.KeyUp}
|
||||||
updatedModel, _ := list.Update(upKey)
|
updatedModel, _ := list.Update(upKey)
|
||||||
list = updatedModel.(*listComponent[testItem])
|
list = updatedModel.(*listComponent[testItem])
|
||||||
_, idx := list.GetSelectedItem()
|
_, idx := list.GetSelectedItem()
|
||||||
if idx != 0 {
|
if idx != 2 {
|
||||||
t.Errorf("Expected to stay at index 0 when pressing up at first item, got %d", idx)
|
t.Errorf("Expected to wrap to index 2 when pressing up at first item, got %d", idx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Move to first item
|
||||||
|
list.SetSelectedIndex(0)
|
||||||
|
|
||||||
// Move to last item
|
// Move to last item
|
||||||
downKey := tea.KeyPressMsg{Code: tea.KeyDown}
|
downKey := tea.KeyPressMsg{Code: tea.KeyDown}
|
||||||
updatedModel, _ = list.Update(downKey)
|
updatedModel, _ = list.Update(downKey)
|
||||||
@@ -158,12 +161,12 @@ func TestNavigationBoundaries(t *testing.T) {
|
|||||||
t.Errorf("Expected to be at index 2, got %d", idx)
|
t.Errorf("Expected to be at index 2, got %d", idx)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test down arrow at last item (should stay at 2)
|
// Test down arrow at last item (should wrap to first item)
|
||||||
updatedModel, _ = list.Update(downKey)
|
updatedModel, _ = list.Update(downKey)
|
||||||
list = updatedModel.(*listComponent[testItem])
|
list = updatedModel.(*listComponent[testItem])
|
||||||
_, idx = list.GetSelectedItem()
|
_, idx = list.GetSelectedItem()
|
||||||
if idx != 2 {
|
if idx != 0 {
|
||||||
t.Errorf("Expected to stay at index 2 when pressing down at last item, got %d", idx)
|
t.Errorf("Expected to wrap to index 0 when pressing down at last item, got %d", idx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -208,3 +211,39 @@ func TestEmptyList(t *testing.T) {
|
|||||||
t.Error("Expected IsEmpty() to return true for empty list")
|
t.Error("Expected IsEmpty() to return true for empty list")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestWrapAroundNavigation(t *testing.T) {
|
||||||
|
list := createTestList()
|
||||||
|
|
||||||
|
// Start at first item (index 0)
|
||||||
|
_, idx := list.GetSelectedItem()
|
||||||
|
if idx != 0 {
|
||||||
|
t.Errorf("Expected to start at index 0, got %d", idx)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Press up arrow - should wrap to last item (index 2)
|
||||||
|
upKey := tea.KeyPressMsg{Code: tea.KeyUp}
|
||||||
|
updatedModel, _ := list.Update(upKey)
|
||||||
|
list = updatedModel.(*listComponent[testItem])
|
||||||
|
_, idx = list.GetSelectedItem()
|
||||||
|
if idx != 2 {
|
||||||
|
t.Errorf("Expected to wrap to index 2 when pressing up from first item, got %d", idx)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Press down arrow - should wrap to first item (index 0)
|
||||||
|
downKey := tea.KeyPressMsg{Code: tea.KeyDown}
|
||||||
|
updatedModel, _ = list.Update(downKey)
|
||||||
|
list = updatedModel.(*listComponent[testItem])
|
||||||
|
_, idx = list.GetSelectedItem()
|
||||||
|
if idx != 0 {
|
||||||
|
t.Errorf("Expected to wrap to index 0 when pressing down from last item, got %d", idx)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Navigate to middle and verify normal navigation still works
|
||||||
|
updatedModel, _ = list.Update(downKey)
|
||||||
|
list = updatedModel.(*listComponent[testItem])
|
||||||
|
_, idx = list.GetSelectedItem()
|
||||||
|
if idx != 1 {
|
||||||
|
t.Errorf("Expected to move to index 1, got %d", idx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user