feat(downloads): add live limits clipboard capture and byte progress

This commit is contained in:
NimBold
2026-07-15 20:35:05 +03:30
parent 9917f29743
commit 1d197432b2
18 changed files with 536 additions and 25 deletions
+29 -2
View File
@@ -6,6 +6,10 @@ import { Play, Pause, MoreVertical, Clock, ArrowUp, ArrowDown } from 'lucide-rea
import type { DownloadItem as DownloadItemType } from '../bindings/DownloadItem';
import { canPauseDownload, canStartDownload, startActionLabel } from '../utils/downloadActions';
import { isActiveDownloadStatus } from '../utils/downloads';
import {
downloadProgressColorClass,
resolveDownloadSizeDisplay
} from '../utils/downloadProgress';
interface DownloadItemProps {
downloadId: string;
@@ -64,6 +68,13 @@ export const DownloadItem = React.memo<DownloadItemProps>(({
: download.status === 'processing'
? 'Muxing...'
: '-';
const sizeDisplay = resolveDownloadSizeDisplay({
downloadedBytes: liveProgress?.downloaded_bytes ?? download.downloadedBytes,
totalBytes: liveProgress?.total_bytes ?? download.totalBytes,
totalIsEstimate: liveProgress?.total_is_estimate ?? download.totalIsEstimate,
fallbackSize: download.size
});
const hasDownloadedAmount = Boolean(sizeDisplay.downloaded && sizeDisplay.total);
return (
<div
@@ -85,8 +96,24 @@ export const DownloadItem = React.memo<DownloadItemProps>(({
</div>
<div className="download-cell-truncate">
<span className="tabular-nums" title={download.size && download.size !== '-' ? download.size : 'Unknown'}>
{download.size && download.size !== '-' ? download.size : 'Unknown'}
<span
className="tabular-nums"
title={hasDownloadedAmount
? `${sizeDisplay.downloaded} downloaded of ${sizeDisplay.totalIsEstimate ? '~' : ''}${sizeDisplay.total}`
: sizeDisplay.fallback}
aria-label={hasDownloadedAmount
? `${sizeDisplay.downloaded} downloaded of ${sizeDisplay.totalIsEstimate ? 'approximately ' : ''}${sizeDisplay.total}`
: sizeDisplay.fallback}
>
{hasDownloadedAmount ? (
<>
<span className={downloadProgressColorClass(download.status)}>{sizeDisplay.downloaded}</span>
<span className="text-text-muted"> / </span>
<span>
{sizeDisplay.totalIsEstimate ? '~' : ''}{sizeDisplay.total}
</span>
</>
) : sizeDisplay.fallback}
</span>
</div>
+30 -1
View File
@@ -10,6 +10,10 @@ import {
isIdentityLocked as getIdentityLocked,
isTransferLocked as getTransferLocked
} from '../utils/downloadActions';
import {
downloadProgressColorClass,
resolveDownloadSizeDisplay
} from '../utils/downloadProgress';
type LoginMode = 'matching' | 'custom' | 'none';
@@ -185,6 +189,13 @@ export const PropertiesModal = () => {
const displayedEta = item.status === 'completed'
? '-'
: liveProgress?.eta ?? item.eta ?? '-';
const sizeDisplay = resolveDownloadSizeDisplay({
downloadedBytes: liveProgress?.downloaded_bytes ?? item.downloadedBytes,
totalBytes: liveProgress?.total_bytes ?? item.totalBytes,
totalIsEstimate: liveProgress?.total_is_estimate ?? item.totalIsEstimate,
fallbackSize: item.size
});
const hasDownloadedAmount = Boolean(sizeDisplay.downloaded && sizeDisplay.total);
let statusColor = 'text-text-secondary';
let StatusIcon = Info;
@@ -221,7 +232,25 @@ export const PropertiesModal = () => {
<div className="grid grid-cols-4 gap-y-2 gap-x-4 text-[11px] leading-tight">
<div className="flex gap-1.5 min-w-0"><span className="text-text-muted font-medium w-[90px] shrink-0">Progress</span><span className="text-text-secondary truncate">{`${(displayedFraction * 100).toFixed(0)}%`}</span></div>
<div className="flex gap-1.5 min-w-0"><span className="text-text-muted font-medium w-[40px] shrink-0">Size</span><span className="text-text-secondary truncate">{item.size || '-'}</span></div>
<div className="flex gap-1.5 min-w-0">
<span className="text-text-muted font-medium w-[40px] shrink-0">Size</span>
<span
className="truncate"
title={hasDownloadedAmount
? `${sizeDisplay.downloaded} downloaded of ${sizeDisplay.totalIsEstimate ? 'approximately ' : ''}${sizeDisplay.total}`
: sizeDisplay.fallback}
>
{hasDownloadedAmount ? (
<>
<span className={downloadProgressColorClass(item.status)}>{sizeDisplay.downloaded}</span>
<span className="text-text-muted"> / </span>
<span className="text-text-secondary">
{sizeDisplay.totalIsEstimate ? '~' : ''}{sizeDisplay.total}
</span>
</>
) : sizeDisplay.fallback}
</span>
</div>
<div className="flex gap-1.5 min-w-0"><span className="text-text-muted font-medium w-[40px] shrink-0">Speed</span><span className="text-text-secondary truncate">{displayedSpeed}</span></div>
<div className="flex gap-1.5 min-w-0"><span className="text-text-muted font-medium w-[30px] shrink-0">ETA</span><span className="text-text-secondary truncate">{displayedEta}</span></div>
+12
View File
@@ -700,6 +700,18 @@ runEngineChecks(false);
className="mac-switch"
/>
</label>
<label className="mac-settings-row cursor-default">
<div className="settings-row-label">
<span>Add clipboard links when Firelink becomes active</span>
<small>Opens supported copied links in the Add window. Off by default.</small>
</div>
<input
type="checkbox"
checked={settings.autoAddClipboardLinks}
onChange={(e) => settings.setAutoAddClipboardLinks(e.target.checked)}
className="mac-switch"
/>
</label>
</div>
</div>
)}