mirror of
https://github.com/nimbold/Firelink.git
synced 2026-08-09 02:40:21 +00:00
feat(downloads): add live limits clipboard capture and byte progress
This commit is contained in:
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user