add upload/download function
This commit is contained in:
124
App.tsx
124
App.tsx
@@ -8,6 +8,7 @@ import SettingsModal from './components/SettingsModal';
|
||||
import SiteManagerModal from './components/SiteManagerModal';
|
||||
import HelpModal from './components/HelpModal';
|
||||
import { CreateFolderModal, RenameModal, DeleteModal } from './components/FileActionModals';
|
||||
import { formatBytes } from './utils/formatters';
|
||||
|
||||
const App: React.FC = () => {
|
||||
// --- State ---
|
||||
@@ -262,7 +263,7 @@ const App: React.FC = () => {
|
||||
|
||||
case 'success':
|
||||
addLog('success', data.message);
|
||||
if (connection.connected) {
|
||||
if (connectionRef.current.connected) {
|
||||
ws?.send(JSON.stringify({ command: 'LIST', path: remote.path }));
|
||||
}
|
||||
ws?.send(JSON.stringify({ command: 'LOCAL_LIST', path: local.path }));
|
||||
@@ -271,6 +272,45 @@ const App: React.FC = () => {
|
||||
case 'sites_list':
|
||||
setSavedSites(data.sites);
|
||||
break;
|
||||
|
||||
case 'transfer_progress':
|
||||
setQueue(prev => prev.map(item => {
|
||||
if (item.id === data.id) {
|
||||
const total = data.bytesOverall;
|
||||
const current = data.bytes;
|
||||
const progress = total > 0 ? Math.round((current / total) * 100) : 0;
|
||||
return { ...item, progress, status: 'transferring', speed: `${formatBytes(current)} transferred` };
|
||||
}
|
||||
return item;
|
||||
}));
|
||||
break;
|
||||
|
||||
case 'transfer_success':
|
||||
setQueue(prev => prev.map(item => {
|
||||
if (item.id === data.id) {
|
||||
return { ...item, progress: 100, status: 'completed', speed: 'Completed' };
|
||||
}
|
||||
return item;
|
||||
}));
|
||||
addLog('success', data.message);
|
||||
// Refresh lists
|
||||
if (data.path) {
|
||||
ws?.send(JSON.stringify({ command: 'LOCAL_LIST', path: local.path }));
|
||||
if (connectionRef.current.connected) {
|
||||
ws?.send(JSON.stringify({ command: 'LIST', path: remote.path }));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'transfer_error':
|
||||
setQueue(prev => prev.map(item => {
|
||||
if (item.id === data.id) {
|
||||
return { ...item, status: 'failed', speed: data.message };
|
||||
}
|
||||
return item;
|
||||
}));
|
||||
addLog('error', data.message);
|
||||
break;
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("WS Message Error", e);
|
||||
@@ -365,6 +405,74 @@ const App: React.FC = () => {
|
||||
if (wsRef.current) wsRef.current.send(JSON.stringify({ command: 'LOCAL_LIST', path }));
|
||||
};
|
||||
|
||||
const handleDownload = () => {
|
||||
if (!connection.connected || selectedRemoteIds.size === 0) return;
|
||||
|
||||
selectedRemoteIds.forEach(id => {
|
||||
const file = remote.files.find(f => f.id === id);
|
||||
if (file && file.type === FileType.FILE) {
|
||||
const transferId = `down-${Date.now()}-${Math.random()}`;
|
||||
const separator = local.path.includes('\\') ? '\\' : '/';
|
||||
const cleanPath = local.path.endsWith(separator) ? local.path : local.path + separator;
|
||||
const localTarget = cleanPath + file.name;
|
||||
const remoteTarget = remote.path === '/' ? `/${file.name}` : `${remote.path}/${file.name}`;
|
||||
|
||||
// Add to Queue
|
||||
setQueue(prev => [...prev, {
|
||||
id: transferId,
|
||||
direction: 'download',
|
||||
filename: file.name,
|
||||
progress: 0,
|
||||
status: 'queued',
|
||||
speed: 'Pending...'
|
||||
}]);
|
||||
|
||||
addLog('command', `DOWNLOAD ${file.name} -> ${localTarget}`);
|
||||
wsRef.current?.send(JSON.stringify({
|
||||
command: 'DOWNLOAD',
|
||||
localPath: localTarget,
|
||||
remotePath: remoteTarget,
|
||||
transferId
|
||||
}));
|
||||
}
|
||||
});
|
||||
setSelectedRemoteIds(new Set());
|
||||
};
|
||||
|
||||
const handleUpload = () => {
|
||||
if (!connection.connected || selectedLocalIds.size === 0) return;
|
||||
|
||||
selectedLocalIds.forEach(id => {
|
||||
const file = local.files.find(f => f.id === id);
|
||||
if (file && file.type === FileType.FILE) {
|
||||
const transferId = `up-${Date.now()}-${Math.random()}`;
|
||||
const separator = local.path.includes('\\') ? '\\' : '/';
|
||||
const cleanPath = local.path.endsWith(separator) ? local.path : local.path + separator;
|
||||
const localSource = cleanPath + file.name;
|
||||
const remoteTarget = remote.path === '/' ? `/${file.name}` : `${remote.path}/${file.name}`;
|
||||
|
||||
// Add to Queue
|
||||
setQueue(prev => [...prev, {
|
||||
id: transferId,
|
||||
direction: 'upload',
|
||||
filename: file.name,
|
||||
progress: 0,
|
||||
status: 'queued',
|
||||
speed: 'Pending...'
|
||||
}]);
|
||||
|
||||
addLog('command', `UPLOAD ${file.name} -> ${remoteTarget}`);
|
||||
wsRef.current?.send(JSON.stringify({
|
||||
command: 'UPLOAD',
|
||||
localPath: localSource,
|
||||
remotePath: remoteTarget,
|
||||
transferId
|
||||
}));
|
||||
}
|
||||
});
|
||||
setSelectedLocalIds(new Set());
|
||||
};
|
||||
|
||||
// --- File Action Handlers ---
|
||||
const initiateCreateFolder = (isLocal: boolean) => {
|
||||
if (!isLocal && !connection.connected) return;
|
||||
@@ -744,10 +852,20 @@ const App: React.FC = () => {
|
||||
|
||||
{/* Middle Actions */}
|
||||
<div className="flex md:flex-col items-center justify-center gap-2 p-1">
|
||||
<button className="p-3 bg-white border border-slate-300 shadow-sm rounded hover:bg-blue-50 text-slate-400">
|
||||
<button
|
||||
className="p-3 bg-white border border-slate-300 shadow-sm rounded hover:bg-blue-50 text-slate-400 hover:text-blue-600 disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
|
||||
onClick={handleUpload}
|
||||
disabled={!connection.connected || selectedLocalIds.size === 0}
|
||||
title="업로드 (Local -> Remote)"
|
||||
>
|
||||
<ArrowRight size={24} strokeWidth={2.5} />
|
||||
</button>
|
||||
<button className="p-3 bg-white border border-slate-300 shadow-sm rounded hover:bg-green-50 text-slate-400">
|
||||
<button
|
||||
className="p-3 bg-white border border-slate-300 shadow-sm rounded hover:bg-green-50 text-slate-400 hover:text-green-600 disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
|
||||
onClick={handleDownload}
|
||||
disabled={!connection.connected || selectedRemoteIds.size === 0}
|
||||
title="다운로드 (Remote -> Local)"
|
||||
>
|
||||
<ArrowLeft size={24} strokeWidth={2.5} />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user