diff --git a/src/renderer/src/components/right-sidebar/FileExplorer.test.tsx b/src/renderer/src/components/right-sidebar/FileExplorer.test.tsx index 0b0dee7079a..f8067c7dfea 100644 --- a/src/renderer/src/components/right-sidebar/FileExplorer.test.tsx +++ b/src/renderer/src/components/right-sidebar/FileExplorer.test.tsx @@ -19,7 +19,8 @@ import { shouldShowFindInFolderAction, shouldShowCopyFileAction, shouldShowOpenInTerminalAction, - shouldShowRemoteDownloadAction + shouldShowRemoteDownloadAction, + shouldShowViewFileAction } from './FileExplorerRow' import { FileExplorerVirtualRows } from './FileExplorerVirtualRows' import type { TreeNode } from './file-explorer-types' @@ -581,6 +582,11 @@ describe('FileExplorerRow collapse folder action', () => { expect(shouldShowOpenInTerminalAction(fileNode)).toBe(false) }) + it('only shows view file for files', () => { + expect(shouldShowViewFileAction(fileNode)).toBe(true) + expect(shouldShowViewFileAction(directoryNode)).toBe(false) + }) + it('shows remote download only for desktop SSH or Remote Host file-like rows', () => { const runtimeContext = { settings: { activeRuntimeEnvironmentId: 'runtime-1' }, @@ -775,6 +781,7 @@ describe('FileExplorerRow collapse folder action', () => { deleteShortcutLabel: 'Del', onClick: vi.fn(), onDoubleClick: vi.fn(), + onViewFile: vi.fn(), onContextMenuSelect: vi.fn(), onCopyPaths: vi.fn(), onStartNew: vi.fn(), @@ -827,6 +834,7 @@ describe('FileExplorerRow collapse folder action', () => { deleteShortcutLabel: 'Del', onClick: vi.fn(), onDoubleClick: vi.fn(), + onViewFile: vi.fn(), onContextMenuSelect: vi.fn(), onCopyPaths: vi.fn(), onStartNew: vi.fn(), @@ -879,6 +887,7 @@ describe('FileExplorerRow collapse folder action', () => { connectionId: 'ssh-1', onClick: vi.fn(), onDoubleClick: vi.fn(), + onViewFile: vi.fn(), onContextMenuSelect: vi.fn(), onCopyPaths: vi.fn(), onStartNew: vi.fn(), @@ -930,6 +939,7 @@ describe('FileExplorerRow collapse folder action', () => { deleteShortcutLabel: 'Del', onClick: vi.fn(), onDoubleClick: vi.fn(), + onViewFile: vi.fn(), onContextMenuSelect: vi.fn(), onCopyPaths: vi.fn(), onStartNew: vi.fn(), @@ -957,4 +967,57 @@ describe('FileExplorerRow collapse folder action', () => { expect(onOpenInTerminal).toHaveBeenCalledWith(directoryNode) }) + + it('passes the row node to the view file handler', () => { + const onViewFile = vi.fn() + const element = FileExplorerVirtualRows({ + virtualizer: { + getTotalSize: () => 26, + getVirtualItems: () => [{ index: 0, key: 'src', start: 0 }], + measureElement: vi.fn() + } as never, + inlineInputIndex: -1, + rowProjection: createFileExplorerRowProjection([fileNode]), + inlineInput: null, + handleInlineSubmit: vi.fn(), + dismissInlineInput: vi.fn(), + folderStatusByRelativePath: new Map(), + statusByRelativePath: new Map(), + ignoredByRelativePath: new Set(), + expanded: new Set(), + dirCache: {}, + selectedPaths: new Set(), + activeFileId: null, + flashingPath: null, + deleteShortcutLabel: 'Del', + onClick: vi.fn(), + onDoubleClick: vi.fn(), + onViewFile, + onContextMenuSelect: vi.fn(), + onCopyPaths: vi.fn(), + onStartNew: vi.fn(), + onStartRename: vi.fn(), + onDuplicate: vi.fn(), + onAddFolderAsProject: vi.fn(), + canAddFolderAsProject: () => false, + onOpenInTerminal: vi.fn(), + onRequestDelete: vi.fn(), + onCollapseFolderSubtree: vi.fn(), + onFindInFolder: vi.fn(), + onMoveDrop: vi.fn(), + onDragTargetChange: vi.fn(), + onDragSourceChange: vi.fn(), + onDragExpandDir: vi.fn(), + onNativeDragTargetChange: vi.fn(), + onNativeDragExpandDir: vi.fn(), + dropTargetDir: null, + dragSourcePath: null, + nativeDropTargetDir: null + }) + + const row = findFileExplorerRow(element) + ;(row.props.onViewFile as () => void)() + + expect(onViewFile).toHaveBeenCalledWith(fileNode) + }) }) diff --git a/src/renderer/src/components/right-sidebar/FileExplorer.tsx b/src/renderer/src/components/right-sidebar/FileExplorer.tsx index 83defe0e715..fb91c21963b 100644 --- a/src/renderer/src/components/right-sidebar/FileExplorer.tsx +++ b/src/renderer/src/components/right-sidebar/FileExplorer.tsx @@ -746,6 +746,7 @@ function FileExplorerFiles(): React.JSX.Element { runtimeDownloadContext={runtimeDownloadContext} onClick={handleRowClick} onDoubleClick={handleDoubleClick} + onViewFile={handleClick} onContextMenuSelect={preserveSelectionForContextMenu} onCopyPaths={copyPathsForNode} onStartNew={startNew} diff --git a/src/renderer/src/components/right-sidebar/FileExplorerRow.tsx b/src/renderer/src/components/right-sidebar/FileExplorerRow.tsx index 765c1071b54..6c4ace896e9 100644 --- a/src/renderer/src/components/right-sidebar/FileExplorerRow.tsx +++ b/src/renderer/src/components/right-sidebar/FileExplorerRow.tsx @@ -279,6 +279,7 @@ type FileExplorerRowProps = { selectionSize: number onClick: (event: React.MouseEvent) => void onDoubleClick: () => void + onViewFile: () => void onContextMenuSelect: () => void onCopyPaths: (pathKind: 'absolute' | 'relative') => void onStartNew: (type: 'file' | 'folder', dir: string, depth: number) => void @@ -310,6 +311,10 @@ export function shouldShowOpenInTerminalAction(node: TreeNode): boolean { return node.isDirectory } +export function shouldShowViewFileAction(node: TreeNode): boolean { + return !node.isDirectory +} + export function shouldShowRemoteDownloadAction( node: TreeNode, connectionId?: string | null, @@ -421,6 +426,7 @@ export function FileExplorerRow({ selectionSize, onClick, onDoubleClick, + onViewFile, onContextMenuSelect, onCopyPaths, onStartNew, @@ -712,6 +718,12 @@ export function FileExplorerRow({ )} )} + {shouldShowViewFileAction(node) && ( + + + {translate('auto.components.right.sidebar.FileExplorerRow.1d8e182c32', 'View File')} + + )} {!node.isDirectory && activeWorktreeId && ( diff --git a/src/renderer/src/components/right-sidebar/FileExplorerVirtualRows.tsx b/src/renderer/src/components/right-sidebar/FileExplorerVirtualRows.tsx index fe4e71dd608..5c64a5a0462 100644 --- a/src/renderer/src/components/right-sidebar/FileExplorerVirtualRows.tsx +++ b/src/renderer/src/components/right-sidebar/FileExplorerVirtualRows.tsx @@ -30,6 +30,7 @@ type FileExplorerVirtualRowsProps = { runtimeDownloadContext?: RuntimeFileOperationArgs | null onClick: (node: TreeNode, event: React.MouseEvent) => void onDoubleClick: (node: TreeNode) => void + onViewFile: (node: TreeNode) => void onContextMenuSelect: (node: TreeNode) => void onCopyPaths: (node: TreeNode, pathKind: 'absolute' | 'relative') => void onStartNew: (type: 'file' | 'folder', parentPath: string, depth: number) => void @@ -74,6 +75,7 @@ export function FileExplorerVirtualRows(props: FileExplorerVirtualRowsProps): Re runtimeDownloadContext, onClick, onDoubleClick, + onViewFile, onContextMenuSelect, onCopyPaths, onStartNew, @@ -180,6 +182,7 @@ export function FileExplorerVirtualRows(props: FileExplorerVirtualRowsProps): Re selectionSize={selectedPaths.has(n.path) ? visibleSelectionCount : 1} onClick={(event) => onClick(n, event)} onDoubleClick={() => onDoubleClick(n)} + onViewFile={() => onViewFile(n)} onContextMenuSelect={() => onContextMenuSelect(n)} onCopyPaths={(pathKind) => onCopyPaths(n, pathKind)} onStartNew={onStartNew} diff --git a/src/renderer/src/components/right-sidebar/FileExplorerVirtualRowsAddProject.test.tsx b/src/renderer/src/components/right-sidebar/FileExplorerVirtualRowsAddProject.test.tsx index 16236cbd71f..d1388383c3f 100644 --- a/src/renderer/src/components/right-sidebar/FileExplorerVirtualRowsAddProject.test.tsx +++ b/src/renderer/src/components/right-sidebar/FileExplorerVirtualRowsAddProject.test.tsx @@ -70,6 +70,7 @@ describe('FileExplorerVirtualRows add-as-project action', () => { deleteShortcutLabel: 'Del', onClick: vi.fn(), onDoubleClick: vi.fn(), + onViewFile: vi.fn(), onContextMenuSelect: vi.fn(), onCopyPaths: vi.fn(), onStartNew: vi.fn(), diff --git a/src/renderer/src/components/right-sidebar/file-explorer-drag-scroll-marker.test.tsx b/src/renderer/src/components/right-sidebar/file-explorer-drag-scroll-marker.test.tsx index a9d1d9a46f5..3e490c7a9a5 100644 --- a/src/renderer/src/components/right-sidebar/file-explorer-drag-scroll-marker.test.tsx +++ b/src/renderer/src/components/right-sidebar/file-explorer-drag-scroll-marker.test.tsx @@ -73,6 +73,7 @@ function virtualRowsElement(nodes: TreeNode[]): React.JSX.Element { onDoubleClick: vi.fn(), onContextMenuSelect: vi.fn(), onCopyPaths: vi.fn(), + onViewFile: vi.fn(), onStartNew: vi.fn(), onStartRename: vi.fn(), onDuplicate: vi.fn(), diff --git a/src/renderer/src/i18n/locales/en.json b/src/renderer/src/i18n/locales/en.json index cf70af13657..2d4efa1e146 100644 --- a/src/renderer/src/i18n/locales/en.json +++ b/src/renderer/src/i18n/locales/en.json @@ -8893,7 +8893,8 @@ "b234ab25b4": "Could not copy the file to the clipboard", "f9d7ca753d": "Copy Paths", "3161c4e425": "folder", - "e887fa4b2e": "Open in Terminal" + "e887fa4b2e": "Open in Terminal", + "1d8e182c32": "View File" }, "FileExplorerToolbar": { "d238264654": "Show Git Ignored Files", diff --git a/src/renderer/src/i18n/locales/es.json b/src/renderer/src/i18n/locales/es.json index 5d9b07de4cd..66a2b10f23b 100644 --- a/src/renderer/src/i18n/locales/es.json +++ b/src/renderer/src/i18n/locales/es.json @@ -8893,7 +8893,8 @@ "b234ab25b4": "No se pudo copiar el archivo en el portapapeles", "f9d7ca753d": "Copiar rutas", "3161c4e425": "carpeta", - "e887fa4b2e": "Abrir en terminal" + "e887fa4b2e": "Abrir en terminal", + "1d8e182c32": "Ver archivo" }, "FileExplorerToolbar": { "d238264654": "Mostrar archivos ignorados por Git", diff --git a/src/renderer/src/i18n/locales/ja.json b/src/renderer/src/i18n/locales/ja.json index cafa057ad53..2b76dba34a1 100644 --- a/src/renderer/src/i18n/locales/ja.json +++ b/src/renderer/src/i18n/locales/ja.json @@ -8893,7 +8893,8 @@ "b234ab25b4": "ファイルをクリップボードにコピーできませんでした", "f9d7ca753d": "パスのコピー", "3161c4e425": "フォルダ", - "e887fa4b2e": "ターミナルで開く" + "e887fa4b2e": "ターミナルで開く", + "1d8e182c32": "ファイルを表示" }, "FileExplorerToolbar": { "d238264654": "Git で無視されたファイルを表示", diff --git a/src/renderer/src/i18n/locales/ko.json b/src/renderer/src/i18n/locales/ko.json index f0e5e2328fa..646b74a42f7 100644 --- a/src/renderer/src/i18n/locales/ko.json +++ b/src/renderer/src/i18n/locales/ko.json @@ -8893,7 +8893,8 @@ "b234ab25b4": "파일을 클립보드에 복사하지 못했습니다", "f9d7ca753d": "경로 복사", "3161c4e425": "폴더", - "e887fa4b2e": "터미널에서 열기" + "e887fa4b2e": "터미널에서 열기", + "1d8e182c32": "파일 보기" }, "FileExplorerToolbar": { "d238264654": "Git이 무시한 파일 표시", diff --git a/src/renderer/src/i18n/locales/zh.json b/src/renderer/src/i18n/locales/zh.json index d00704947fa..66de9505f78 100644 --- a/src/renderer/src/i18n/locales/zh.json +++ b/src/renderer/src/i18n/locales/zh.json @@ -8893,7 +8893,8 @@ "b234ab25b4": "无法将文件复制到剪贴板", "f9d7ca753d": "复制路径", "3161c4e425": "文件夹", - "e887fa4b2e": "在终端中打开" + "e887fa4b2e": "在终端中打开", + "1d8e182c32": "查看文件" }, "FileExplorerToolbar": { "d238264654": "显示 Git 忽略的文件",