|
10 | 10 | initialPath: string |
11 | 11 | fileService?: FileService |
12 | 12 | isFocused?: boolean |
| 13 | + showHiddenFiles?: boolean |
13 | 14 | onPathChange?: (path: string) => void |
14 | 15 | onRequestFocus?: () => void |
15 | 16 | } |
|
18 | 19 | initialPath, |
19 | 20 | fileService = defaultFileService, |
20 | 21 | isFocused = false, |
| 22 | + showHiddenFiles = true, |
21 | 23 | onPathChange, |
22 | 24 | onRequestFocus, |
23 | 25 | }: Props = $props() |
24 | 26 |
|
25 | 27 | let currentPath = $state(initialPath) |
26 | | - let files = $state<FileEntry[]>([]) |
| 28 | + let allFiles = $state<FileEntry[]>([]) |
27 | 29 | let loading = $state(true) |
28 | 30 | let error = $state<string | null>(null) |
29 | 31 | let selectedIndex = $state(0) |
30 | 32 | let fileListRef: FileList | undefined = $state() |
31 | 33 |
|
| 34 | + // Filter files based on showHiddenFiles setting |
| 35 | + // Always keep ".." visible for parent navigation |
| 36 | + function filterFiles(entries: FileEntry[], showHidden: boolean): FileEntry[] { |
| 37 | + if (showHidden) return entries |
| 38 | + return entries.filter((e) => !e.name.startsWith('.') || e.name === '..') |
| 39 | + } |
| 40 | +
|
| 41 | + // Compute visible files based on showHiddenFiles prop |
| 42 | + const files = $derived(filterFiles(allFiles, showHiddenFiles)) |
| 43 | +
|
32 | 44 | // Create ".." entry for parent navigation |
33 | 45 | function createParentEntry(path: string): FileEntry | null { |
34 | 46 | if (path === '/') return null |
|
46 | 58 | try { |
47 | 59 | const entries = await fileService.listDirectory(path) |
48 | 60 | const parentEntry = createParentEntry(path) |
49 | | - files = parentEntry ? [parentEntry, ...entries] : entries |
| 61 | + allFiles = parentEntry ? [parentEntry, ...entries] : entries |
50 | 62 |
|
51 | 63 | // If selectName is provided, find and select that entry |
| 64 | + // But only if it's visible (not filtered out) |
52 | 65 | if (selectName) { |
53 | | - const targetIndex = files.findIndex((f) => f.name === selectName) |
| 66 | + const visibleFiles = filterFiles(allFiles, showHiddenFiles) |
| 67 | + const targetIndex = visibleFiles.findIndex((f) => f.name === selectName) |
| 68 | + // If target is hidden (e.g., navigating up from .config with hidden files off), |
| 69 | + // fall back to index 0 |
54 | 70 | selectedIndex = targetIndex >= 0 ? targetIndex : 0 |
55 | 71 | } else { |
56 | 72 | selectedIndex = 0 |
57 | 73 | } |
58 | 74 | } catch (e) { |
59 | 75 | error = e instanceof Error ? e.message : String(e) |
60 | | - files = [] |
| 76 | + allFiles = [] |
61 | 77 | } finally { |
62 | 78 | loading = false |
63 | 79 | } |
|
120 | 136 | } |
121 | 137 | }) |
122 | 138 |
|
| 139 | + // Reset selection when showHiddenFiles changes and current selection becomes invalid |
| 140 | + $effect(() => { |
| 141 | + // Re-run when files change (which depends on showHiddenFiles) |
| 142 | + if (selectedIndex >= files.length && files.length > 0) { |
| 143 | + selectedIndex = 0 |
| 144 | + // eslint-disable-next-line @typescript-eslint/no-unsafe-call |
| 145 | + fileListRef?.scrollToIndex(0) |
| 146 | + } |
| 147 | + }) |
| 148 | +
|
123 | 149 | onMount(() => { |
124 | 150 | void loadDirectory(currentPath) |
125 | 151 | }) |
|
0 commit comments