From 5aa0359a93fb09fd668c3851e91da158e70f349b Mon Sep 17 00:00:00 2001 From: Sucukdeluxe Date: Fri, 21 Aug 2026 10:34:13 +0200 Subject: [PATCH] feat(statistics): keep large totals precise in gigabytes --- src/renderer/views/statistics/StatisticsView.tsx | 8 ++++---- tests/statistics-view.test.tsx | 15 +++++++++++++++ 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/renderer/views/statistics/StatisticsView.tsx b/src/renderer/views/statistics/StatisticsView.tsx index 140f263..f7cf965 100644 --- a/src/renderer/views/statistics/StatisticsView.tsx +++ b/src/renderer/views/statistics/StatisticsView.tsx @@ -32,7 +32,7 @@ const rangeItems: Array<{ id: StatisticsRange; label: string }> = [ const numberFormatter = new Intl.NumberFormat("de-DE", { maximumFractionDigits: 1 }); -function formatBytes(bytes: number): string { +function formatBytes(bytes: number, maximumUnitIndex = Number.POSITIVE_INFINITY): string { const safe = Math.max(0, Number.isFinite(bytes) ? bytes : 0); if (safe < 1024) { return `${Math.round(safe)} B`; @@ -40,7 +40,7 @@ function formatBytes(bytes: number): string { const units = ["KB", "MB", "GB", "TB", "PB"]; let value = safe / 1024; let unitIndex = 0; - while (value >= 1024 && unitIndex < units.length - 1) { + while (value >= 1024 && unitIndex < units.length - 1 && unitIndex < maximumUnitIndex) { value /= 1024; unitIndex += 1; } @@ -51,8 +51,8 @@ function formatMetric(metric: StatisticsMetric, kind: "bytes" | "count" | "perce if (!metric.available || metric.value === null) { return "–"; } - if (kind === "bytes") { - return formatBytes(metric.value); + if (kind === "bytes") { + return formatBytes(metric.value, 2); } if (kind === "speed") { return `${formatBytes(metric.value)}/s`; diff --git a/tests/statistics-view.test.tsx b/tests/statistics-view.test.tsx index 60546c5..548d9b0 100644 --- a/tests/statistics-view.test.tsx +++ b/tests/statistics-view.test.tsx @@ -392,6 +392,21 @@ describe("statistics model", () => { }); describe("statistics view", () => { + it("keeps large statistic data volumes precise in gigabytes instead of rounding to terabytes", () => { + const snapshot = createSnapshot(); + let ledger = createStatisticsLedger(now); + ledger = recordStatisticsBytes(ledger, "realdebrid", 1_250 * 1024 ** 3, now); + snapshot.stats.statistics = ledger; + const model = buildStatisticsViewModel(snapshot, "today", now); + const html = renderToStaticMarkup(<> + + } model={model} /> + ); + + expect(html.match(/1\.250 GB/g)).toHaveLength(2); + expect(html).toContain("1,2 TB"); + }); + it("marks statistic ranges for one measured vertical selection indicator", () => { const model = buildStatisticsViewModel(createSnapshot(), "today", now); const html = renderToStaticMarkup();