@@ -17,6 +17,10 @@ import { useFreebuffModelStore } from '../state/freebuff-model-store'
1717import { useFreebuffSessionStore } from '../state/freebuff-session-store'
1818import { useTerminalDimensions } from '../hooks/use-terminal-dimensions'
1919import { useTheme } from '../hooks/use-theme'
20+ import {
21+ nextSelectableFreebuffModelId ,
22+ resolveFreebuffModelCommitTarget ,
23+ } from '../utils/freebuff-model-navigation'
2024
2125import type { KeyEvent } from '@opentui/core'
2226
@@ -173,30 +177,32 @@ export const FreebuffModelSelector: React.FC = () => {
173177 name === 'return' || name === 'enter' || name === 'space'
174178 if ( ! isForward && ! isBackward && ! isCommit ) return
175179 if ( isCommit ) {
176- if (
177- focusedId !== committedModelId &&
178- isFreebuffModelAvailable ( focusedId , new Date ( now ) )
179- ) {
180+ const targetId = resolveFreebuffModelCommitTarget ( {
181+ focusedId,
182+ selectedId : selectedModel ,
183+ committedId : committedModelId ,
184+ isSelectable : ( modelId ) =>
185+ isFreebuffModelAvailable ( modelId , new Date ( now ) ) ,
186+ } )
187+ if ( targetId ) {
180188 key . preventDefault ?.( )
181- pick ( focusedId )
189+ pick ( targetId )
182190 }
183191 return
184192 }
185- const currentIdx = FREEBUFF_MODEL_SELECTOR_MODELS . findIndex (
186- ( m ) => m . id === focusedId ,
187- )
188- if ( currentIdx === - 1 ) return
189- const len = FREEBUFF_MODEL_SELECTOR_MODELS . length
190- const nextIdx = isForward
191- ? ( currentIdx + 1 ) % len
192- : ( currentIdx - 1 + len ) % len
193- const target = FREEBUFF_MODEL_SELECTOR_MODELS [ nextIdx ]
194- if ( target ) {
193+ const targetId = nextSelectableFreebuffModelId ( {
194+ modelIds : FREEBUFF_MODEL_SELECTOR_MODELS . map ( ( model ) => model . id ) ,
195+ focusedId,
196+ direction : isForward ? 'forward' : 'backward' ,
197+ isSelectable : ( modelId ) =>
198+ isFreebuffModelAvailable ( modelId , new Date ( now ) ) ,
199+ } )
200+ if ( targetId ) {
195201 key . preventDefault ?.( )
196- setFocusedId ( target . id )
202+ setFocusedId ( targetId )
197203 }
198204 } ,
199- [ pending , pick , focusedId , committedModelId , now ] ,
205+ [ pending , pick , focusedId , selectedModel , committedModelId , now ] ,
200206 ) ,
201207 )
202208
@@ -219,7 +225,8 @@ export const FreebuffModelSelector: React.FC = () => {
219225 // 'Selected' means the dot is filled and the label is bold. On the
220226 // landing screen ('none') this tracks the pre-focused pick; on the
221227 // queued screen it tracks the model the server has us on. Either
222- // way, selectedModel reflects the intent of "what Enter commits to."
228+ // way, selectedModel is the safe fallback if focus ever lands on a
229+ // closed row (for example when deployment hours change).
223230 const isSelected = model . id === selectedModel
224231 const isHovered = hoveredId === model . id
225232 const isFocused = focusedId === model . id && ! isSelected
0 commit comments