@@ -79,7 +79,7 @@ export function getFileIcon(fileName: string, isDirectory: boolean) {
7979}
8080
8181/**
82- * Sorts an array of FileEntry.
82+ * Sorts an array of FileEntry, always keeping the parent directory ("../") at the top .
8383 * If no column is provided, sorts directories first, then files, each group by name using natural order.
8484 * If a column is provided, sorts by that column (respecting direction), ignoring directory/file type.
8585 *
@@ -95,53 +95,69 @@ export function sortFiles(
9595) : FileEntry [ ] {
9696 const sorted = [ ...files ] ;
9797
98- // Default sort: directories first, then files, both sorted by name (natural, case‑insensitive)
98+ // Helper to wrap a comparator and always put the parent directory first
99+ const withParentPriority = ( compareFn : ( a : FileEntry , b : FileEntry ) => number ) => {
100+ return ( a : FileEntry , b : FileEntry ) : number => {
101+ const aIsParent = a . link === '../' ;
102+ const bIsParent = b . link === '../' ;
103+
104+ if ( aIsParent && ! bIsParent ) return - 1 ; // parent comes first
105+ if ( ! aIsParent && bIsParent ) return 1 ; // parent comes first
106+ if ( aIsParent && bIsParent ) return 0 ; // both parent (shouldn't happen)
107+
108+ // Normal comparison
109+ return compareFn ( a , b ) ;
110+ } ;
111+ } ;
112+
113+ // Default sort: directories first, then name natural order
99114 if ( column == null ) {
100- return sorted . sort ( ( a , b ) => {
101- // Directories first
102- if ( a . isDirectory !== b . isDirectory ) {
103- return a . isDirectory ? - 1 : 1 ;
104- }
105- // Same type → natural sort by name
106- return naturalCompare ( a . name , b . name ) ;
107- } ) ;
115+ return sorted . sort (
116+ withParentPriority ( ( a , b ) => {
117+ if ( a . isDirectory !== b . isDirectory ) {
118+ return a . isDirectory ? - 1 : 1 ;
119+ }
120+ return naturalCompare ( a . name , b . name ) ;
121+ } )
122+ ) ;
108123 }
109124
110125 // Column‑based sort – direction defaults to 'asc'
111126 const dir = direction ?? 'asc' ;
112127 const multiplier = dir === 'asc' ? 1 : - 1 ;
113128
114- return sorted . sort ( ( a , b ) => {
115- let cmp = 0 ;
116-
117- switch ( column ) {
118- case 'name' :
119- cmp = naturalCompare ( a . name , b . name ) ;
120- break ;
121-
122- case 'size' :
123- // Nulls always last
124- if ( a . size === null && b . size === null ) cmp = 0 ;
125- else if ( a . size === null ) cmp = 1 ; // a is null → a after b
126- else if ( b . size === null ) cmp = - 1 ; // b is null → a before b
127- else cmp = a . size . bytes - b . size . bytes ;
128- break ;
129-
130- case 'date' :
131- if ( a . date === null && b . date === null ) cmp = 0 ;
132- else if ( a . date === null ) cmp = 1 ;
133- else if ( b . date === null ) cmp = - 1 ;
134- else cmp = a . date . getTime ( ) - b . date . getTime ( ) ;
135- break ;
136-
137- default :
138- // Exhaustiveness check
139- const _ : never = column ;
140- return 0 ;
141- }
129+ return sorted . sort (
130+ withParentPriority ( ( a , b ) => {
131+ let cmp = 0 ;
132+
133+ switch ( column ) {
134+ case ' name' :
135+ cmp = naturalCompare ( a . name , b . name ) ;
136+ break ;
137+
138+ case 'size' :
139+ if ( a . size === null && b . size === null ) cmp = 0 ;
140+ else if ( a . size === null ) cmp = 1 ; // nulls last
141+ else if ( b . size === null ) cmp = - 1 ;
142+ else cmp = a . size . bytes - b . size . bytes ;
143+ break ;
144+
145+ case 'date' :
146+ if ( a . date === null && b . date === null ) cmp = 0 ;
147+ else if ( a . date === null ) cmp = 1 ;
148+ else if ( b . date === null ) cmp = - 1 ;
149+ else cmp = a . date . getTime ( ) - b . date . getTime ( ) ;
150+ break ;
151+
152+ default :
153+ // Exhaustiveness check
154+ const _ : never = column ;
155+ return 0 ;
156+ }
142157
143- return cmp * multiplier ;
144- } ) ;
158+ return cmp * multiplier ;
159+ } )
160+ ) ;
145161}
146162
147163/**
0 commit comments