import React, { useState, useEffect, useCallback } from 'react' import { Folder, FileText, 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] = useState('') const [files, setFiles] = useState([]) const [loading, setLoading] = useState(false) const [pathHistory, setPathHistory] = useState(['']) const loadFiles = 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]) 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 = (file: RemoteFileItem) => { const newPath = currentPath ? `${currentPath}/${file.name}` : file.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()}
{ if ((e.target as HTMLElement).classList.contains('space-y-1') || (e.target as HTMLElement).classList.contains('p-2')) { onSelect(null) } }}> {loading ? (
加载中...
) : files.length === 0 ? (
空文件夹
) : (
{files.map((file) => (
onSelect(selectedFile?.path === file.path ? null : file)} onDoubleClick={() => file.type === 'dir' && handleGoInto(file)} className={clsx( 'flex items-center gap-2 px-2 py-1.5 rounded-md cursor-pointer transition-colors text-sm', selectedFile?.path === file.path ? 'bg-gray-100 text-gray-800 dark:bg-gray-700/60 dark:text-gray-200' : 'hover:bg-gray-100 dark:hover:bg-gray-700/50 text-gray-700 dark:text-gray-200' )} > {file.type === 'dir' ? ( ) : ( )} {file.name}
))}
)}
) }