Files
waste-go/web/src/components/Transfers.tsx

52 lines
2.1 KiB
TypeScript
Raw Normal View History

import { useWaste } from '../store'
function fmt(bytes: number): string {
if (bytes < 1024) return `${bytes} B`
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`
}
export function Transfers() {
const { pendingOffers, fileProgress, acceptOffer, rejectOffer, cancelTransfer, connectedPeers } = useWaste()
const hasPending = Object.keys(pendingOffers).length > 0
const hasActive = Object.keys(fileProgress).length > 0
if (!hasPending && !hasActive) return null
function alias(peerId: string) {
return connectedPeers.find(p => p.id === peerId)?.alias ?? peerId.slice(0, 8)
}
return (
<div className="sidebar-section">
<span className="sidebar-label">Transfers</span>
{Object.entries(pendingOffers).map(([xid, offer]) => (
<div key={xid} className="transfer-row">
<span className="transfer-name" title={offer.name}>{offer.name}</span>
<span className="transfer-meta">{fmt(offer.size)} from {alias(offer.peerId)}</span>
<div className="transfer-actions">
<button className="transfer-btn accept" onClick={() => acceptOffer(offer.peerId, xid, offer.name, offer.size)}>Accept</button>
<button className="transfer-btn reject" onClick={() => rejectOffer(offer.peerId, xid)}>Reject</button>
</div>
</div>
))}
{Object.entries(fileProgress).map(([xid, p]) => {
const pct = p.total > 0 ? Math.round((p.received / p.total) * 100) : 0
return (
<div key={xid} className="transfer-row">
<span className="transfer-name" title={p.name}>{p.name}</span>
<span className="transfer-meta">{fmt(p.received)} / {fmt(p.total)} · {alias(p.peerId)}</span>
<div className="transfer-progress">
<div className="transfer-progress-bar" style={{ width: `${pct}%` }} />
</div>
<button className="transfer-btn reject" onClick={() => cancelTransfer(p.peerId, xid, 'recv')}>Cancel</button>
</div>
)
})}
</div>
)
}