From bfb901903dd5197f7928ca5dfdfc303b02543ea1 Mon Sep 17 00:00:00 2001 From: Sucukdeluxe Date: Wed, 12 Aug 2026 00:16:26 +0200 Subject: [PATCH] fix(downloads): harden compact finalization status Use the compact finalization text for status-cell titles so item tooltips cannot expose raw archive details in German or English. Require exactly two non-empty finite fraction values with one slash and a positive total before deriving progress. Invalid, infinite, NaN, zero-total, and extra-part forms now resolve to the phase only, with regression coverage for every case. --- src/renderer/views/downloads/DownloadsTable.tsx | 10 ++++++---- tests/downloads-view.test.tsx | 7 +++++++ 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/renderer/views/downloads/DownloadsTable.tsx b/src/renderer/views/downloads/DownloadsTable.tsx index af94fee..ff92873 100644 --- a/src/renderer/views/downloads/DownloadsTable.tsx +++ b/src/renderer/views/downloads/DownloadsTable.tsx @@ -157,9 +157,10 @@ export function compactDownloadStatus(value: string): string { if (finalizing) { const fraction = status.match(/\(([^)]*)\)/); if (fraction) { - const [currentValue, totalValue] = fraction[1].split("/"); - const current = Number(currentValue?.trim()); - const total = Number(totalValue?.trim()); + const values = fraction[1].split("/"); + if (values.length !== 2 || values.some((value) => !value.trim())) return finalizing[1]; + const current = Number(values[0]); + const total = Number(values[1]); if (Number.isFinite(current) && Number.isFinite(total) && total > 0) return `${finalizing[1]} - ${progress((current / total) * 100)}%`; return finalizing[1]; } @@ -184,8 +185,9 @@ function DownloadMeter({ value, text }: { value: number; text: string }): ReactE function DownloadStatusCell({ status, title }: { status: string; title?: string }): ReactElement { const visibleStatus = compactDownloadStatus(status); + const statusTitle = /^(Finalisieren|Finalizing)\b/i.test(status) ? visibleStatus : title || status; return ( - + diff --git a/tests/downloads-view.test.tsx b/tests/downloads-view.test.tsx index 7531d93..8bcf9f6 100644 --- a/tests/downloads-view.test.tsx +++ b/tests/downloads-view.test.tsx @@ -957,11 +957,18 @@ describe("download table row contracts", () => { expect(html).toContain(`aria-label="${expectedStatus}"`); expect(html.match(new RegExp(`>${expectedStatus}`, "g"))).toHaveLength(2); expect(html).not.toContain(">release.part1.rar"); + if (target === "item") expect(html).not.toMatch(/title="[^"]*release\.part1\.rar/); }); it.each([ ["Finalisieren (3/2) · release.part1.rar", "Finalisieren - 100%"], ["Finalizing (-1/2) · release.part1.rar", "Finalizing - 0%"], + ["Finalisieren (/2) · release.part1.rar", "Finalisieren"], + ["Finalizing (1/) · release.part1.rar", "Finalizing"], + ["Finalisieren (1/2/3) · release.part1.rar", "Finalisieren"], + ["Finalizing (not-a-number/2) · release.part1.rar", "Finalizing"], + ["Finalisieren (Infinity/2) · release.part1.rar", "Finalisieren"], + ["Finalizing (NaN/2) · release.part1.rar", "Finalizing"], ["Finalisieren (1/0) · release.part1.rar", "Finalisieren"], ["Finalizing (invalid/2) · release.part1.rar", "Finalizing"] ])("derives only finite finalization percentages", (rawStatus, expectedStatus) => {