|
89 | 89 | let loading = false; |
90 | 90 | let error: string | null = null; |
91 | 91 |
|
| 92 | + // ── Navigation history ────────────────────────────────────────────── |
| 93 | + type NavEntry = { path: string; file: string | null }; |
| 94 | + let navHistory: NavEntry[] = []; |
| 95 | + let navIndex = -1; |
| 96 | + let navigatingHistory = false; |
| 97 | +
|
| 98 | + $: canGoBack = navIndex > 0; |
| 99 | + $: canGoForward = navIndex < navHistory.length - 1; |
| 100 | +
|
| 101 | + const pushNavHistory = (path: string, file: string | null = null) => { |
| 102 | + if (navigatingHistory) return; |
| 103 | + // Skip if this is the same as the current entry |
| 104 | + const current = navHistory[navIndex]; |
| 105 | + if (current && current.path === path && current.file === file) return; |
| 106 | + // Truncate forward history when navigating to a new location |
| 107 | + if (navIndex < navHistory.length - 1) { |
| 108 | + navHistory = navHistory.slice(0, navIndex + 1); |
| 109 | + } |
| 110 | + navHistory = [...navHistory, { path, file }]; |
| 111 | + navIndex = navHistory.length - 1; |
| 112 | + }; |
| 113 | +
|
| 114 | + const goBack = async () => { |
| 115 | + if (!canGoBack) return; |
| 116 | + navigatingHistory = true; |
| 117 | + navIndex -= 1; |
| 118 | + const entry = navHistory[navIndex]; |
| 119 | + await loadDir(entry.path); |
| 120 | + if (entry.file) { |
| 121 | + const fileName = entry.file.split('/').pop() ?? ''; |
| 122 | + await openEntry({ name: fileName, type: 'file', size: 0 }); |
| 123 | + } |
| 124 | + navigatingHistory = false; |
| 125 | + }; |
| 126 | +
|
| 127 | + const goForward = async () => { |
| 128 | + if (!canGoForward) return; |
| 129 | + navigatingHistory = true; |
| 130 | + navIndex += 1; |
| 131 | + const entry = navHistory[navIndex]; |
| 132 | + await loadDir(entry.path); |
| 133 | + if (entry.file) { |
| 134 | + const fileName = entry.file.split('/').pop() ?? ''; |
| 135 | + await openEntry({ name: fileName, type: 'file', size: 0 }); |
| 136 | + } |
| 137 | + navigatingHistory = false; |
| 138 | + }; |
| 139 | +
|
92 | 140 | // ── File preview state ─────────────────────────────────────────────── |
93 | 141 | let selectedFile: string | null = null; |
94 | 142 | let previewPort: number | null = null; |
|
259 | 307 | clearFilePreview(); |
260 | 308 | currentPath = path; |
261 | 309 | savedPath = path; |
| 310 | + pushNavHistory(path); |
262 | 311 |
|
263 | 312 | const result = await listFiles(terminal.url, terminal.key, path); |
264 | 313 | loading = false; |
|
284 | 333 | return; |
285 | 334 | } |
286 | 335 |
|
| 336 | + const filePath = `${currentPath}${entry.name}`; |
| 337 | + pushNavHistory(currentPath, filePath); |
| 338 | +
|
287 | 339 | const terminal = selectedTerminal; |
288 | 340 | if (!terminal) return; |
289 | 341 |
|
290 | | - const filePath = `${currentPath}${entry.name}`; |
291 | 342 | selectedFile = filePath; |
292 | 343 | fileLoading = true; |
293 | 344 | clearFilePreview(); |
|
659 | 710 | breadcrumbs={buildBreadcrumbs(currentPath)} |
660 | 711 | {selectedFile} |
661 | 712 | {loading} |
| 713 | + {canGoBack} |
| 714 | + {canGoForward} |
| 715 | + onGoBack={goBack} |
| 716 | + onGoForward={goForward} |
662 | 717 | onNavigate={loadDir} |
663 | 718 | onRefresh={() => { |
664 | 719 | if (selectedFile) { |
|
0 commit comments