Merge Größe/Geladen into single progress bar column (JDownloader 2 style)
Some checks are pending
Build and Release / build (push) Waiting to run

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Sucukdeluxe 2026-03-02 23:16:45 +01:00
parent cb66661d9b
commit 578d050926
3 changed files with 82 additions and 17 deletions

View File

@ -1,6 +1,6 @@
{ {
"name": "real-debrid-downloader", "name": "real-debrid-downloader",
"version": "1.5.29", "version": "1.5.30",
"description": "Real-Debrid Downloader Desktop (Electron + React + TypeScript)", "description": "Real-Debrid Downloader Desktop (Electron + React + TypeScript)",
"main": "build/main/main/main.js", "main": "build/main/main/main.js",
"author": "Sucukdeluxe", "author": "Sucukdeluxe",

View File

@ -2077,11 +2077,10 @@ export function App(): ReactElement {
</div> </div>
<div className="pkg-column-header"> <div className="pkg-column-header">
{(["name", "size", "hoster"] as PkgSortColumn[]).flatMap((col) => { {(["name", "size", "hoster"] as PkgSortColumn[]).flatMap((col) => {
const labels: Record<PkgSortColumn, string> = { name: "Name", size: "Größe", hoster: "Hoster" }; const labels: Record<PkgSortColumn, string> = { name: "Name", size: "Geladen / Größe", hoster: "Hoster" };
const isActive = downloadsSortColumn === col; const isActive = downloadsSortColumn === col;
const before: React.ReactNode[] = []; const before: React.ReactNode[] = [];
if (col === "size") before.push(<span key="progress" className="pkg-col pkg-col-progress">Fortschritt</span>); if (col === "size") before.push(<span key="progress" className="pkg-col pkg-col-progress">Fortschritt</span>);
if (col === "hoster") before.push(<span key="downloaded" className="pkg-col pkg-col-downloaded">Geladen</span>);
return [ return [
...before, ...before,
<span <span
@ -2179,8 +2178,15 @@ export function App(): ReactElement {
<h4>{entry.name}</h4> <h4>{entry.name}</h4>
</div> </div>
<span className="pkg-col pkg-col-progress">{entry.status === "completed" ? "100%" : "-"}</span> <span className="pkg-col pkg-col-progress">{entry.status === "completed" ? "100%" : "-"}</span>
<span className="pkg-col pkg-col-size">{humanSize(entry.totalBytes)}</span> <span className="pkg-col pkg-col-size">{(() => {
<span className="pkg-col pkg-col-downloaded">{humanSize(entry.downloadedBytes)}</span> const pct = entry.totalBytes > 0 ? Math.min(100, Math.round((entry.downloadedBytes / entry.totalBytes) * 100)) : 0;
return entry.totalBytes > 0 ? (
<span className="progress-size">
<span className="progress-size-bar" style={{ width: `${pct}%` }} />
<span className="progress-size-text">{humanSize(entry.downloadedBytes)} / {humanSize(entry.totalBytes)}</span>
</span>
) : "-";
})()}</span>
<span className="pkg-col pkg-col-hoster">{entry.provider ? providerLabels[entry.provider] : "-"}</span> <span className="pkg-col pkg-col-hoster">{entry.provider ? providerLabels[entry.provider] : "-"}</span>
<span className="pkg-col pkg-col-status">{entry.status === "completed" ? "Abgeschlossen" : "Gelöscht"}</span> <span className="pkg-col pkg-col-status">{entry.status === "completed" ? "Abgeschlossen" : "Gelöscht"}</span>
<span className="pkg-col pkg-col-speed">-</span> <span className="pkg-col pkg-col-speed">-</span>
@ -2806,8 +2812,17 @@ const PackageCard = memo(function PackageCard({ pkg, items, packageSpeed, isFirs
<span className="progress-inline-text">{dlProgress}%</span> <span className="progress-inline-text">{dlProgress}%</span>
</span> </span>
</span> </span>
<span className="pkg-col pkg-col-size">{humanSize(items.reduce((sum, item) => sum + (item.totalBytes || item.downloadedBytes || 0), 0))}</span> <span className="pkg-col pkg-col-size">{(() => {
<span className="pkg-col pkg-col-downloaded">{humanSize(items.reduce((sum, item) => sum + (item.downloadedBytes || 0), 0))}</span> const totalBytes = items.reduce((sum, item) => sum + (item.totalBytes || item.downloadedBytes || 0), 0);
const dlBytes = items.reduce((sum, item) => sum + (item.downloadedBytes || 0), 0);
const pct = totalBytes > 0 ? Math.min(100, Math.round((dlBytes / totalBytes) * 100)) : 0;
return totalBytes > 0 ? (
<span className="progress-size">
<span className="progress-size-bar" style={{ width: `${pct}%` }} />
<span className="progress-size-text">{humanSize(dlBytes)} / {humanSize(totalBytes)}</span>
</span>
) : "-";
})()}</span>
<span className="pkg-col pkg-col-hoster" title={(() => { <span className="pkg-col pkg-col-hoster" title={(() => {
const hosters = [...new Set(items.map((item) => formatHoster(item)).filter((h) => h !== "-"))]; const hosters = [...new Set(items.map((item) => formatHoster(item)).filter((h) => h !== "-"))];
return hosters.join(", "); return hosters.join(", ");
@ -2837,8 +2852,17 @@ const PackageCard = memo(function PackageCard({ pkg, items, packageSpeed, isFirs
</span> </span>
) : "-"} ) : "-"}
</span> </span>
<span className="pkg-col pkg-col-size">{(item.totalBytes || item.downloadedBytes) ? humanSize(item.totalBytes || item.downloadedBytes || 0) : "-"}</span> <span className="pkg-col pkg-col-size">{(() => {
<span className="pkg-col pkg-col-downloaded">{item.downloadedBytes > 0 ? humanSize(item.downloadedBytes) : "-"}</span> const total = item.totalBytes || item.downloadedBytes || 0;
const dl = item.downloadedBytes || 0;
const pct = total > 0 ? Math.min(100, Math.round((dl / total) * 100)) : 0;
return total > 0 ? (
<span className="progress-size progress-size-small">
<span className="progress-size-bar" style={{ width: `${pct}%` }} />
<span className="progress-size-text">{humanSize(dl)} / {humanSize(total)}</span>
</span>
) : "-";
})()}</span>
<span className="pkg-col pkg-col-hoster" title={formatHoster(item)}>{formatHoster(item)}</span> <span className="pkg-col pkg-col-hoster" title={formatHoster(item)}>{formatHoster(item)}</span>
<span className="pkg-col pkg-col-status" title={item.fullStatus}> <span className="pkg-col pkg-col-status" title={item.fullStatus}>
{item.fullStatus} {item.fullStatus}

View File

@ -577,7 +577,7 @@ body,
.pkg-column-header { .pkg-column-header {
display: grid; display: grid;
grid-template-columns: 1fr 70px 90px 90px 220px 180px 100px; grid-template-columns: 1fr 70px 160px 220px 180px 100px;
gap: 8px; gap: 8px;
padding: 5px 12px; padding: 5px 12px;
background: var(--card); background: var(--card);
@ -603,7 +603,7 @@ body,
.pkg-columns { .pkg-columns {
display: grid; display: grid;
grid-template-columns: 1fr 70px 90px 90px 220px 180px 100px; grid-template-columns: 1fr 70px 160px 220px 180px 100px;
gap: 8px; gap: 8px;
align-items: center; align-items: center;
min-width: 0; min-width: 0;
@ -624,7 +624,6 @@ body,
} }
.pkg-columns .pkg-col-progress, .pkg-columns .pkg-col-progress,
.pkg-columns .pkg-col-downloaded,
.pkg-columns .pkg-col-size, .pkg-columns .pkg-col-size,
.pkg-columns .pkg-col-hoster, .pkg-columns .pkg-col-hoster,
.pkg-columns .pkg-col-status, .pkg-columns .pkg-col-status,
@ -636,11 +635,55 @@ body,
white-space: nowrap; white-space: nowrap;
} }
.pkg-col-progress, .pkg-col-progress {
.pkg-col-downloaded {
font-variant-numeric: tabular-nums; font-variant-numeric: tabular-nums;
} }
.progress-size {
display: block;
position: relative;
width: 100%;
height: 18px;
background: var(--progress-track);
border-radius: 4px;
overflow: hidden;
}
.progress-size-bar {
position: absolute;
top: 0;
left: 0;
height: 100%;
background: linear-gradient(90deg, #3bc9ff, #22d3ee);
border-radius: 4px;
transition: width 0.15s ease;
}
.progress-size-text {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
font-size: 10px;
font-weight: 600;
font-variant-numeric: tabular-nums;
color: var(--text);
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);
white-space: nowrap;
}
.progress-size-small {
height: 14px;
}
.progress-size-small .progress-size-text {
font-size: 9px;
}
.progress-inline { .progress-inline {
display: block; display: block;
position: relative; position: relative;
@ -1189,7 +1232,7 @@ td {
.item-row { .item-row {
display: grid; display: grid;
grid-template-columns: 1fr 70px 90px 90px 220px 180px 100px; grid-template-columns: 1fr 70px 160px 220px 180px 100px;
gap: 8px; gap: 8px;
align-items: center; align-items: center;
margin: 0 -12px; margin: 0 -12px;
@ -1649,7 +1692,6 @@ td {
} }
.pkg-column-header .pkg-col-progress, .pkg-column-header .pkg-col-progress,
.pkg-column-header .pkg-col-downloaded,
.pkg-column-header .pkg-col-size, .pkg-column-header .pkg-col-size,
.pkg-column-header .pkg-col-hoster, .pkg-column-header .pkg-col-hoster,
.pkg-column-header .pkg-col-status, .pkg-column-header .pkg-col-status,
@ -1658,7 +1700,6 @@ td {
} }
.pkg-columns .pkg-col-progress, .pkg-columns .pkg-col-progress,
.pkg-columns .pkg-col-downloaded,
.pkg-columns .pkg-col-size, .pkg-columns .pkg-col-size,
.pkg-columns .pkg-col-hoster, .pkg-columns .pkg-col-hoster,
.pkg-columns .pkg-col-status, .pkg-columns .pkg-col-status,