on main help sign in
fix(ui): model dialog: skip non-model items when navigating selection
commit5df46965eb6221b8a524f0c8a3b0d6c5b61f71fb authorAyman Bagabas <ayman.bagabas@gmail.com> dateMon 5 Jan 2026, 11:28 (1 year ago) parent876048d
2 files changed+73−2
internal/ui/dialog/models_list.go+72−1 internal/ui/model/ui.go+1−1
internal/ui/dialog/models_list.go+72−1
@@ -55,6 +55,28 @@ func (f *ModelsList) SetFilter(q string) {
5555 f.query = q
5656}
5757
58+// SetSelected sets the selected item index. It overrides the base method to
59+// skip non-model items.
60+func (f *ModelsList) SetSelected(index int) {
61+ if index < 0 || index >= f.Len() {
62+ f.List.SetSelected(index)
63+ return
64+ }
65+
66+ f.List.SetSelected(index)
67+ for {
68+ selectedItem := f.List.SelectedItem()
69+ if _, ok := selectedItem.(*ModelItem); ok {
70+ return
71+ }
72+ f.List.SetSelected(index + 1)
73+ index++
74+ if index >= f.Len() {
75+ return
76+ }
77+ }
78+}
79+
5880// SetSelectedItem sets the selected item in the list by item ID.
5981func (f *ModelsList) SetSelectedItem(itemID string) {
6082 if itemID == "" {
@@ -74,14 +96,63 @@ func (f *ModelsList) SetSelectedItem(itemID string) {
7496 }
7597}
7698
99+// SelectNext selects the next model item, skipping any non-focusable items
100+// like group headers and spacers.
101+func (f *ModelsList) SelectNext() (v bool) {
102+ for {
103+ v = f.List.SelectNext()
104+ selectedItem := f.List.SelectedItem()
105+ if _, ok := selectedItem.(*ModelItem); ok {
106+ return v
107+ }
108+ }
109+}
110+
111+// SelectPrev selects the previous model item, skipping any non-focusable items
112+// like group headers and spacers.
113+func (f *ModelsList) SelectPrev() (v bool) {
114+ for {
115+ v = f.List.SelectPrev()
116+ selectedItem := f.List.SelectedItem()
117+ if _, ok := selectedItem.(*ModelItem); ok {
118+ return v
119+ }
120+ }
121+}
122+
123+// SelectFirst selects the first model item in the list.
124+func (f *ModelsList) SelectFirst() (v bool) {
125+ v = f.List.SelectFirst()
126+ for {
127+ selectedItem := f.List.SelectedItem()
128+ if _, ok := selectedItem.(*ModelItem); ok {
129+ return v
130+ }
131+ v = f.List.SelectNext()
132+ }
133+}
134+
135+// SelectLast selects the last model item in the list.
136+func (f *ModelsList) SelectLast() (v bool) {
137+ v = f.List.SelectLast()
138+ for {
139+ selectedItem := f.List.SelectedItem()
140+ if _, ok := selectedItem.(*ModelItem); ok {
141+ return v
142+ }
143+ v = f.List.SelectPrev()
144+ }
145+}
146+
77147// VisibleItems returns the visible items after filtering.
78148func (f *ModelsList) VisibleItems() []list.Item {
79− if len(f.query) == 0 {
149+ if f.query == "" {
80150 // No filter, return all items with group headers
81151 items := []list.Item{}
82152 for _, g := range f.groups {
83153 items = append(items, &g)
84154 for _, item := range g.Items {
155+ item.SetMatch(fuzzy.Match{})
85156 items = append(items, item)
86157 }
87158 // Add a space separator after each provider section
internal/ui/model/ui.go+1−1
@@ -728,7 +728,7 @@ func (m *UI) handleKeyPressMsg(msg tea.KeyPressMsg) tea.Cmd {
728728 return tea.Batch(cmds...)
729729}
730730
731−// Draw implements [tea.Layer] and draws the UI model.
731+// Draw implements [uv.Drawable] and draws the UI model.
732732func (m *UI) Draw(scr uv.Screen, area uv.Rectangle) {
733733 layout := m.generateLayout(area.Dx(), area.Dy())
734734