@@ -272,16 +272,16 @@ const toUiPath = (p: string) => isWin ? p.replaceAll('\\', '/') : p
272272 */
273273const filterByFileTypes = ( choices : Choice [ ] , fileTypes : string [ ] | undefined ) : Choice [ ] => {
274274 if ( ! fileTypes ) return choices
275-
275+
276276 return choices . filter ( ( choice ) => {
277277 // Always include directories (identified by folder.svg icon)
278278 if ( choice . img ?. includes ( 'folder.svg' ) ) {
279279 return true
280280 }
281-
281+
282282 // Check file extension
283283 const ext = ogPath . extname ( choice . value )
284-
284+
285285 // Include files with matching extensions
286286 // Exclude files without extensions (like README, Makefile) when fileTypes is specified
287287 return ext && fileTypes . includes ( ext )
@@ -311,7 +311,7 @@ const getWindowsRoots = async (): Promise<string[]> => {
311311
312312export const createPathChoices = async (
313313 startPath : string ,
314- { dirFilter = ( dirent ) => true , dirSort = ( a , b ) => 0 , onlyDirs = false , statFn = statAsync , fileTypes, useSessionCache = true } : {
314+ { dirFilter = ( dirent ) => true , dirSort = ( a , b ) => 0 , onlyDirs = false , statFn = statAsync , fileTypes, useSessionCache = true } : {
315315 dirFilter ?: ( dirent : any ) => boolean
316316 dirSort ?: ( a : any , b : any ) => number
317317 onlyDirs ?: boolean
@@ -456,7 +456,7 @@ export const createPathChoices = async (
456456
457457 const mapped = await mapDirents ( folders . concat ( files ) )
458458 const sorted = mapped . sort ( dirSort )
459-
459+
460460 // Apply fileTypes filtering if specified
461461 return filterByFileTypes ( sorted , fileTypes )
462462}
@@ -614,13 +614,15 @@ ${pathError.hint ? `**Hint:** ${pathError.hint}` : ''}
614614 }
615615
616616 let upDir = async ( dir ) => {
617+ global . log ( `[path] upDir called: dir.name=${ dir ?. name } , dir.value=${ dir ?. value } , dir.miss=${ dir ?. miss } ` )
617618 if ( dir ?. miss ) {
618619 return
619620 }
620621
621622 // Get the current path from the actual input state, not startPath
622623 // This ensures we're always working with the most current value
623624 const currentPath = global . __kitPromptState ?. input || currentInput || startPath
625+ global . log ( `[path] upDir: currentPath=${ currentPath } , startPath=${ startPath } ` )
624626
625627 // Save the current selection in navigation history before going up
626628 if ( dir ?. name && currentPath ) {
@@ -673,14 +675,17 @@ ${pathError.hint ? `**Hint:** ${pathError.hint}` : ''}
673675 }
674676
675677 let downDir = async ( dir ) => {
678+ global . log ( `[path] downDir called: dir.name=${ dir ?. name } , dir.value=${ dir ?. value } , dir.miss=${ dir ?. miss } ` )
676679 if ( dir ?. miss ) {
677680 return
678681 }
679682
680683 // Get the current path from the actual input state, not startPath
681684 const currentPath = global . __kitPromptState ?. input || currentInput || startPath
685+ global . log ( `[path] downDir: currentPath=${ currentPath } , startPath=${ startPath } ` )
682686
683687 let targetPath = typeof dir === 'string' ? ogPath . resolve ( currentPath , dir ) : dir . value
688+ global . log ( `[path] downDir: targetPath=${ targetPath } ` )
684689 let allowed = true
685690 let needsPermission =
686691 targetPath === home ( 'Downloads' ) || targetPath === home ( 'Documents' ) || targetPath === home ( 'Desktop' )
@@ -830,20 +835,52 @@ Please grant permission in System Preferences > Security & Privacy > Privacy > F
830835 }
831836
832837 let onRight = ( input , state : AppState ) => {
838+ global . log ( `[path] onRight called: input=${ input } , flaggedValue=${ state ?. flaggedValue } , focused=${ state ?. focused ?. name } ` )
833839 if ( ! state . flaggedValue ) {
834- downDir ( state . focused )
840+ // Handle case where focused is stale/invalid (e.g., __app__/no-choice sentinel)
841+ // This can happen due to timing issues when the renderer hasn't updated focusedChoiceAtom yet
842+ const focused = state . focused
843+ if ( ! focused ?. value || focused ?. name === '__app__/no-choice' ) {
844+ global . log ( `[path] onRight: focused is invalid (${ focused ?. name } ), using first available choice` )
845+ // Try to get the first valid choice from kitPrevChoices
846+ const firstChoice = global . kitPrevChoices ?. find ( c => c ?. value && ! c ?. miss && c ?. name !== '__app__/no-choice' )
847+ if ( firstChoice ) {
848+ global . log ( `[path] onRight: using fallback choice: ${ firstChoice . name } ` )
849+ downDir ( firstChoice )
850+ } else {
851+ global . log ( `[path] onRight: no valid fallback choice available` )
852+ }
853+ } else {
854+ downDir ( focused )
855+ }
835856 }
836857 }
837858
838859 let onLeft = ( input , state ) => {
860+ global . log ( `[path] onLeft called: input=${ input } , flaggedValue=${ state ?. flaggedValue } , focused=${ state ?. focused ?. name } ` )
839861 if ( ! state . flaggedValue ) {
840- upDir ( state . focused )
862+ // Handle case where focused is stale/invalid - upDir doesn't strictly need a valid focused
863+ // since it navigates up regardless, but we pass the focused for history tracking
864+ const focused = state . focused
865+ if ( ! focused ?. value || focused ?. name === '__app__/no-choice' ) {
866+ global . log ( `[path] onLeft: focused is invalid (${ focused ?. name } ), using first available choice` )
867+ const firstChoice = global . kitPrevChoices ?. find ( c => c ?. value && ! c ?. miss && c ?. name !== '__app__/no-choice' )
868+ upDir ( firstChoice || focused )
869+ } else {
870+ upDir ( focused )
871+ }
841872 }
842873 }
843874
844875 // Map FORWARD/BACK channels to right/left navigation
845- let onForward = onRight
846- let onBack = onLeft
876+ let onForward = ( input , state ) => {
877+ global . log ( `[path] onForward called: input=${ input } ` )
878+ onRight ( input , state )
879+ }
880+ let onBack = ( input , state ) => {
881+ global . log ( `[path] onBack called: input=${ input } ` )
882+ onLeft ( input , state )
883+ }
847884
848885 let sort = 'name'
849886 let dir = 'desc'
0 commit comments