From 60feca71a6a77b7d1eef1c172a61624d5fe48150 Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Thu, 13 Aug 2026 14:50:43 -0600 Subject: [PATCH] refac --- src/lib/components/chat/FileNav.svelte | 25 +- .../chat/FileNav/FileEntryRow.svelte | 21 +- .../chat/FileNav/FileTypeIcon.svelte | 15 + src/lib/components/chat/FileNav/Icon.svelte | 703 ++++++++++++++++++ src/lib/components/chat/FileNav/fileIcon.ts | 162 ++++ 5 files changed, 889 insertions(+), 37 deletions(-) create mode 100644 src/lib/components/chat/FileNav/FileTypeIcon.svelte create mode 100644 src/lib/components/chat/FileNav/Icon.svelte create mode 100644 src/lib/components/chat/FileNav/fileIcon.ts diff --git a/src/lib/components/chat/FileNav.svelte b/src/lib/components/chat/FileNav.svelte index 2c82ef9abe..c4e645bbd2 100644 --- a/src/lib/components/chat/FileNav.svelte +++ b/src/lib/components/chat/FileNav.svelte @@ -30,8 +30,6 @@ type TerminalCwd } from '$lib/apis/terminal'; import { isCodeFile } from '$lib/utils/codeHighlight'; - import Folder from '../icons/Folder.svelte'; - import Document from '../icons/Document.svelte'; import PenAlt from '../icons/PenAlt.svelte'; import ZoomReset from '../icons/ZoomReset.svelte'; import { isSavedChatId, isTemporaryChatId } from '$lib/utils/chatId'; @@ -43,6 +41,8 @@ import FileNavToolbar from './FileNav/FileNavToolbar.svelte'; import FilePreview from './FileNav/FilePreview.svelte'; import FileEntryRow from './FileNav/FileEntryRow.svelte'; + import Icon from './FileNav/Icon.svelte'; + import FileTypeIcon from './FileNav/FileTypeIcon.svelte'; import BulkActionBar from './FileNav/BulkActionBar.svelte'; import PortList from './FileNav/PortList.svelte'; import PortPreview from './FileNav/PortPreview.svelte'; @@ -1014,14 +1014,14 @@ {:else if terminalChatContextPending}
- +
{$i18n.t('Start the chat to use this terminal.')}
{:else if !selectedTerminal}
- +
{$i18n.t('No Terminal connection configured.')}
@@ -1451,7 +1451,7 @@ {#if !loading && !error && !uploading && !($selectedTerminalId && $terminalServers === null)} {#if creatingFolder}
- + - + - - - + {$i18n.t('Terminal')} {#if terminalExpanded} diff --git a/src/lib/components/chat/FileNav/FileEntryRow.svelte b/src/lib/components/chat/FileNav/FileEntryRow.svelte index 0dff841d37..defdaab477 100644 --- a/src/lib/components/chat/FileNav/FileEntryRow.svelte +++ b/src/lib/components/chat/FileNav/FileEntryRow.svelte @@ -6,11 +6,11 @@ import Dropdown from '$lib/components/common/Dropdown.svelte'; import DropdownMenu from '$lib/components/common/DropdownMenu.svelte'; - import Folder from '../../icons/Folder.svelte'; import EllipsisHorizontal from '../../icons/EllipsisHorizontal.svelte'; import GarbageBin from '../../icons/GarbageBin.svelte'; import Pencil from '../../icons/Pencil.svelte'; import Clipboard from '../../icons/Clipboard.svelte'; + import FileTypeIcon from './FileTypeIcon.svelte'; const i18n: any = getContext('i18n'); @@ -250,24 +250,7 @@ {/if}
{/if} - {#if entry.type === 'directory'} - - {:else} - - - - {/if} + {#if renaming} + import Icon from './Icon.svelte'; + import { fileIconName } from './fileIcon'; + + export let name = ''; + export let type = 'file'; + export let size = 14; + export let strokeWidth = 1.4; + + $: iconName = fileIconName(name, type); + $: tone = + type === 'directory' ? 'text-gray-500 dark:text-gray-400' : 'text-gray-400 dark:text-gray-500'; + + + diff --git a/src/lib/components/chat/FileNav/Icon.svelte b/src/lib/components/chat/FileNav/Icon.svelte new file mode 100644 index 0000000000..1227ad1713 --- /dev/null +++ b/src/lib/components/chat/FileNav/Icon.svelte @@ -0,0 +1,703 @@ + + + + {#if name === 'folder'} + + {:else if name === 'page'} + + + {:else if name === 'page-text'} + + + + + + {:else if name === 'terminal'} + + + {:else if name === 'tools'} + + + + + {:else if name === 'search'} + + + {:else if name === 'git-diff'} + + + + {:else if name === 'git-branch'} + + + + + {:else if name === 'chat-fork'} + + + + + + {:else if name === 'chat-bubble'} + + {:else if name === 'chat-plus'} + + + + {:else if name === 'info'} + + + + {:else if name === 'brain'} + + + + + + + {:else if name === 'spark'} + + {:else if name === 'plus'} + + {:else if name === 'xmark'} + + {:else if name === 'menu'} + + + + {:else if name === 'expand'} + + + + + {:else if name === 'sidebar-expand'} + + + + {:else if name === 'settings'} + + + {:else if name === 'usage'} + + + + + + + {:else if name === 'half-moon'} + + {:else if name === 'sun-light'} + + + + + {:else if name === 'code'} + + + + {:else if name === 'python'} + + + + + + + {:else if name === 'javascript-logo'} + + JS + {:else if name === 'typescript-logo'} + + TS + {:else if name === 'react'} + + + + + {:else if name === 'rust'} + + + R + {:else if name === 'go-logo'} + + + + GO + {:else if name === 'java-logo'} + + + + + + {:else if name === 'c-logo'} + + C + {:else if name === 'cpp-logo'} + + C + + {:else if name === 'c-sharp-logo'} + + C# + {:else if name === 'ruby-logo'} + + + + {:else if name === 'php-logo'} + + PHP + {:else if name === 'kotlin-logo'} + + + + {:else if name === 'svelte-logo'} + + + + {:else if name === 'vue-js'} + + + {:else if name === 'apple-swift'} + + {:else if name === 'markdown-logo'} + + + + {:else if name === 'json-logo'} + + + + {:else if name === 'yaml-logo'} + + + + + + {:else if name === 'xml-logo'} + + + + {:else if name === 'shell-logo'} + + + + {:else if name === 'html5'} + + + {:else if name === 'css3'} + + + + {:else if name === 'svg-format'} + + + + + + {:else if name === 'database-script'} + + + {:else if name === 'csv-logo'} + + + CSV + {:else if name === 'pdf-logo'} + + + PDF + {:else if name === 'npm'} + + + + + + + + {:else if name === 'archive'} + + + + + {:else if name === 'package'} + + + {:else if name === 'package-lock'} + + + + {:else if name === 'list'} + + + + + + + {:else if name === 'split-view'} + + + {:else if name === 'chevron-right'} + + {:else if name === 'arrow-left'} + + {:else if name === 'log-out'} + + + {:else if name === 'user'} + + + + {:else if name === 'lock'} + + {:else if name === 'docker'} + + {:else if name === 'empty-page'} + + + {:else if name === 'monitor'} + + + + + {:else if name === 'phone'} + + + {:else if name === 'chevron-left'} + + {:else if name === 'check'} + + {:else if name === 'upload'} + + + {:else if name === 'three-dots'} + + + + {:else if name === 'trash'} + + + {:else if name === 'pencil'} + + {:else if name === 'download'} + + + {:else if name === 'eye'} + + + {:else if name === 'minus'} + + {:else if name === 'chevron-up'} + + {:else if name === 'chevron-down'} + + {:else if name === 'expand'} + + + + + {:else if name === 'collapse'} + + + + + {:else if name === 'refresh'} + + + + + {:else if name === 'copy'} + + + {:else if name === 'sort'} + + + + {:else if name === 'external-link'} + + + + {:else if name === 'save'} + + + + {:else if name === 'shield'} + + {:else if name === 'gateway'} + + + + {:else if name === 'quote'} + + + + + {:else if name === 'undo'} + + + {:else if name === 'redo'} + + + {:else if name === 'list-ordered'} + + + + + + + {:else if name === 'check-square'} + + + {:else if name === 'table'} + + + + + {:else if name === 'image'} + + + + {:else if name === 'split-horizontal'} + + + + {:else if name === 'split-vertical'} + + + + {:else if name === 'arrow-right-from-line'} + + + + {:else if name === 'swap'} + + + + + {:else if name === 'plug'} + + + + + + + + + {:else if name === 'play'} + + {:else if name === 'clock'} + + + {:else if name === 'cube'} + + + + {:else if name === 'telegram'} + + {:else if name === 'discord'} + + + + + + {:else if name === 'slack'} + + + + + {:else if name === 'whatsapp'} + + + {:else if name === 'signal'} + + + {:else if name === 'browser'} + + + + + {:else if name === 'globe'} + + + + + + + {:else if name === 'microphone'} + + + + + {:else if name === 'speaker'} + + + + {:else if name === 'stop'} + + {:else if name === 'share'} + + + + + + {:else if name === 'wifi-off'} + + + + + + + {/if} + diff --git a/src/lib/components/chat/FileNav/fileIcon.ts b/src/lib/components/chat/FileNav/fileIcon.ts new file mode 100644 index 0000000000..b7c12397dd --- /dev/null +++ b/src/lib/components/chat/FileNav/fileIcon.ts @@ -0,0 +1,162 @@ +/** + * Shared file icon name resolver. + * Maps file names/extensions to Icon component names. + */ + +export function fileIconName(name: string, type: string = 'file'): string { + if (type === 'directory') return 'folder'; + const base = name.split('/').pop() ?? name; + const lower = base.toLowerCase(); + const ext = base.includes('.') ? (base.split('.').pop()?.toLowerCase() ?? '') : ''; + + if (lower === 'dockerfile' || lower === 'containerfile') return 'docker'; + if (lower === 'license' || lower === 'license.md') return 'page-text'; + if (lower === 'package.json' || lower === 'npm-shrinkwrap.json' || lower === 'bunfig.toml') { + return 'npm'; + } + if ( + lower.endsWith('.lock') || + lower === 'package-lock.json' || + lower === 'pnpm-lock.yaml' || + lower === 'yarn.lock' + ) { + return 'package-lock'; + } + + switch (ext) { + case 'md': + case 'mdx': + case 'markdown': + return 'markdown-logo'; + case 'ts': + return 'typescript-logo'; + case 'tsx': + return 'react'; + case 'js': + case 'mjs': + case 'cjs': + return 'javascript-logo'; + case 'jsx': + return 'react'; + case 'py': + case 'pyw': + return 'python'; + case 'rs': + return 'rust'; + case 'go': + return 'go-logo'; + case 'java': + return 'java-logo'; + case 'c': + case 'h': + return 'c-logo'; + case 'cpp': + case 'cc': + case 'cxx': + case 'hpp': + case 'hh': + case 'hxx': + return 'cpp-logo'; + case 'cs': + return 'c-sharp-logo'; + case 'rb': + return 'ruby-logo'; + case 'php': + return 'php-logo'; + case 'swift': + return 'apple-swift'; + case 'kt': + case 'kts': + return 'kotlin-logo'; + case 'svelte': + return 'svelte-logo'; + case 'vue': + return 'vue-js'; + case 'json': + case 'jsonc': + case 'json5': + return 'json-logo'; + case 'yaml': + case 'yml': + return 'yaml-logo'; + case 'toml': + case 'ini': + case 'cfg': + case 'conf': + case 'env': + return 'settings'; + case 'sh': + case 'bash': + case 'zsh': + case 'fish': + return 'shell-logo'; + case 'html': + case 'htm': + return 'html5'; + case 'css': + case 'scss': + case 'sass': + case 'less': + return 'css3'; + case 'xml': + return 'xml-logo'; + case 'svg': + return 'svg-format'; + case 'sql': + case 'sqlite': + case 'sqlite3': + case 'db': + case 'db3': + return 'database-script'; + case 'csv': + case 'tsv': + return 'csv-logo'; + case 'pdf': + return 'pdf-logo'; + case 'jpg': + case 'jpeg': + case 'png': + case 'gif': + case 'webp': + case 'bmp': + case 'ico': + case 'avif': + case 'tiff': + return 'image'; + case 'mp4': + case 'webm': + case 'mov': + case 'ogv': + case 'avi': + case 'mkv': + return 'play'; + case 'mp3': + case 'wav': + case 'ogg': + case 'flac': + case 'm4a': + case 'aac': + case 'opus': + case 'wma': + return 'speaker'; + case 'zip': + case 'tar': + case 'gz': + case 'tgz': + case 'bz2': + case 'xz': + case '7z': + case 'rar': + return 'archive'; + case 'docx': + case 'txt': + return 'page-text'; + case 'xlsx': + case 'xls': + return 'table'; + case 'pptx': + return 'page'; + default: + return 'empty-page'; + } +}