Skip to content

Commit 3a4b862

Browse files
committed
refac
1 parent 637cd13 commit 3a4b862

2 files changed

Lines changed: 94 additions & 1 deletion

File tree

src/lib/components/chat/FileNav.svelte

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,54 @@
8989
let loading = false;
9090
let error: string | null = null;
9191
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+
92140
// ── File preview state ───────────────────────────────────────────────
93141
let selectedFile: string | null = null;
94142
let previewPort: number | null = null;
@@ -259,6 +307,7 @@
259307
clearFilePreview();
260308
currentPath = path;
261309
savedPath = path;
310+
pushNavHistory(path);
262311
263312
const result = await listFiles(terminal.url, terminal.key, path);
264313
loading = false;
@@ -284,10 +333,12 @@
284333
return;
285334
}
286335
336+
const filePath = `${currentPath}${entry.name}`;
337+
pushNavHistory(currentPath, filePath);
338+
287339
const terminal = selectedTerminal;
288340
if (!terminal) return;
289341
290-
const filePath = `${currentPath}${entry.name}`;
291342
selectedFile = filePath;
292343
fileLoading = true;
293344
clearFilePreview();
@@ -659,6 +710,10 @@
659710
breadcrumbs={buildBreadcrumbs(currentPath)}
660711
{selectedFile}
661712
{loading}
713+
{canGoBack}
714+
{canGoForward}
715+
onGoBack={goBack}
716+
onGoForward={goForward}
662717
onNavigate={loadDir}
663718
onRefresh={() => {
664719
if (selectedFile) {

src/lib/components/chat/FileNav/FileNavToolbar.svelte

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,12 @@
2020
export let onUploadFiles: (files: File[]) => void = () => {};
2121
export let onMove: (source: string, destFolder: string) => void = () => {};
2222
23+
// Back / forward navigation
24+
export let canGoBack = false;
25+
export let canGoForward = false;
26+
export let onGoBack: () => void = () => {};
27+
export let onGoForward: () => void = () => {};
28+
2329
let dragOverCrumb: number | null = null;
2430
2531
let uploadInput: HTMLInputElement;
@@ -32,6 +38,38 @@
3238
</script>
3339

3440
<div class="flex items-center px-2 pb-1.5 shrink-0 gap-1">
41+
<!-- Back -->
42+
<Tooltip content={$i18n.t('Back')}>
43+
<button
44+
class="shrink-0 p-1 rounded transition {canGoBack
45+
? 'text-gray-400 dark:text-gray-500 hover:bg-gray-100 dark:hover:bg-gray-800 hover:text-gray-600 dark:hover:text-gray-400'
46+
: 'text-gray-200 dark:text-gray-700 cursor-default'}"
47+
on:click={onGoBack}
48+
disabled={!canGoBack}
49+
aria-label={$i18n.t('Back')}
50+
>
51+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="size-3.5">
52+
<path fill-rule="evenodd" d="M11.78 5.22a.75.75 0 0 1 0 1.06L8.06 10l3.72 3.72a.75.75 0 1 1-1.06 1.06l-4.25-4.25a.75.75 0 0 1 0-1.06l4.25-4.25a.75.75 0 0 1 1.06 0Z" clip-rule="evenodd" />
53+
</svg>
54+
</button>
55+
</Tooltip>
56+
57+
<!-- Forward -->
58+
<Tooltip content={$i18n.t('Forward')}>
59+
<button
60+
class="shrink-0 p-1 rounded transition {canGoForward
61+
? 'text-gray-400 dark:text-gray-500 hover:bg-gray-100 dark:hover:bg-gray-800 hover:text-gray-600 dark:hover:text-gray-400'
62+
: 'text-gray-200 dark:text-gray-700 cursor-default'}"
63+
on:click={onGoForward}
64+
disabled={!canGoForward}
65+
aria-label={$i18n.t('Forward')}
66+
>
67+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="size-3.5">
68+
<path fill-rule="evenodd" d="M8.22 5.22a.75.75 0 0 1 1.06 0l4.25 4.25a.75.75 0 0 1 0 1.06l-4.25 4.25a.75.75 0 1 1-1.06-1.06L11.94 10 8.22 6.28a.75.75 0 0 1 0-1.06Z" clip-rule="evenodd" />
69+
</svg>
70+
</button>
71+
</Tooltip>
72+
3573
<div
3674
bind:this={breadcrumbEl}
3775
class="flex items-center flex-1 min-w-0 overflow-x-auto scrollbar-none"

0 commit comments

Comments
 (0)