import React from 'react' import { Folder, FileText, ArrowDown, ChevronRight, ChevronLeft, RefreshCw } from 'lucide-react' import { clsx } from 'clsx' import { fetchRemoteFiles, type RemoteFileItem } from '../../api' interface RemoteFilePanelProps { serverHost: string port: number password?: string selectedFile: RemoteFileItem | null onSelect: (file: RemoteFileItem | null) => void onDownload: () => void disabled?: boolean } export const RemoteFilePanel: React.FC = ({ serverHost, port, password, selectedFile, onSelect, onDownload, disabled, }) => { const [currentPath, setCurrentPath] = React.useState('') const [files, setFiles] = React.useState([]) const [loading, setLoading] = React.useState(false) const [pathHistory, setPathHistory] = React.useState(['']) const loadFiles = React.useCallback(async (path: string) => { setLoading(true) try { const items = await fetchRemoteFiles(serverHost, port, path, password) setFiles(items) } catch (err) { console.error('Failed to load remote files:', err) setFiles([]) } finally { setLoading(false) } }, [serverHost, port, password]) React.useEffect(() => { loadFiles(currentPath) }, [currentPath, loadFiles]) const handleGoBack = () => { if (pathHistory.length > 1) { const newHistory = [...pathHistory] newHistory.pop() const prevPath = newHistory[newHistory.length - 1] setPathHistory(newHistory) setCurrentPath(prevPath) onSelect(null) } } const handleGoInto = (folder: RemoteFileItem) => { const newPath = currentPath ? `${currentPath}/${folder.name}` : folder.name setPathHistory([...pathHistory, newPath]) setCurrentPath(newPath) onSelect(null) } const handleRefresh = () => { loadFiles(currentPath) } const getDisplayPath = () => { if (!currentPath) return '远程文件' const parts = currentPath.split('/') return parts[parts.length - 1] || currentPath } return (
{getDisplayPath()}
{loading ? (
加载中...
) : files.length === 0 ? (
空文件夹
) : (
{files.map((file) => (
onSelect(file.type === 'dir' ? null : file)} onDoubleClick={() => file.type === 'dir' && handleGoInto(file)} className={clsx( 'flex items-center gap-2 px-2 py-1.5 rounded cursor-pointer transition-colors', selectedFile?.path === file.path ? 'bg-blue-100 dark:bg-blue-900/30' : 'hover:bg-gray-100 dark:hover:bg-gray-700/50' )} > {file.type === 'dir' ? ( ) : ( )} {file.name} {selectedFile?.path === file.path && (
)}
))}
)}
) }