@@ -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
@@ -169,30 +173,32 @@ export const FreebuffModelSelector: React.FC = () => {
169173 const isCommit = name === 'return' || name === 'enter' || name === 'space'
170174 if ( ! isForward && ! isBackward && ! isCommit ) return
171175 if ( isCommit ) {
172- if (
173- focusedId !== committedModelId &&
174- isFreebuffModelAvailable ( focusedId , new Date ( now ) )
175- ) {
176+ const targetId = resolveFreebuffModelCommitTarget ( {
177+ focusedId,
178+ selectedId : selectedModel ,
179+ committedId : committedModelId ,
180+ isSelectable : ( modelId ) =>
181+ isFreebuffModelAvailable ( modelId , new Date ( now ) ) ,
182+ } )
183+ if ( targetId ) {
176184 key . preventDefault ?.( )
177- pick ( focusedId )
185+ pick ( targetId )
178186 }
179187 return
180188 }
181- const currentIdx = FREEBUFF_MODEL_SELECTOR_MODELS . findIndex (
182- ( m ) => m . id === focusedId ,
183- )
184- if ( currentIdx === - 1 ) return
185- const len = FREEBUFF_MODEL_SELECTOR_MODELS . length
186- const nextIdx = isForward
187- ? ( currentIdx + 1 ) % len
188- : ( currentIdx - 1 + len ) % len
189- const target = FREEBUFF_MODEL_SELECTOR_MODELS [ nextIdx ]
190- if ( target ) {
189+ const targetId = nextSelectableFreebuffModelId ( {
190+ modelIds : FREEBUFF_MODEL_SELECTOR_MODELS . map ( ( model ) => model . id ) ,
191+ focusedId,
192+ direction : isForward ? 'forward' : 'backward' ,
193+ isSelectable : ( modelId ) =>
194+ isFreebuffModelAvailable ( modelId , new Date ( now ) ) ,
195+ } )
196+ if ( targetId ) {
191197 key . preventDefault ?.( )
192- setFocusedId ( target . id )
198+ setFocusedId ( targetId )
193199 }
194200 } ,
195- [ pending , pick , focusedId , committedModelId , now ] ,
201+ [ pending , pick , focusedId , selectedModel , committedModelId , now ] ,
196202 ) ,
197203 )
198204
@@ -215,7 +221,8 @@ export const FreebuffModelSelector: React.FC = () => {
215221 // 'Selected' means the dot is filled and the label is bold. On the
216222 // landing screen ('none') this tracks the pre-focused pick; on the
217223 // queued screen it tracks the model the server has us on. Either
218- // way, selectedModel reflects the intent of "what Enter commits to."
224+ // way, selectedModel is the safe fallback if focus ever lands on a
225+ // closed row (for example when deployment hours change).
219226 const isSelected = model . id === selectedModel
220227 const isHovered = hoveredId === model . id
221228 const isFocused = focusedId === model . id && ! isSelected
0 commit comments