fix(downloads): stabilize remaining metric updates
This commit is contained in:
@@ -22,6 +22,10 @@ export function getRollingMetricDirection(previous: number, next: number): Rolli
|
|||||||
return "none";
|
return "none";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function shouldAnimateRollingMetric(previousValue: string, nextValue: string): boolean {
|
||||||
|
return previousValue !== nextValue;
|
||||||
|
}
|
||||||
|
|
||||||
export function RollingMetricValue({ numericValue, value }: RollingMetricValueProps): ReactElement {
|
export function RollingMetricValue({ numericValue, value }: RollingMetricValueProps): ReactElement {
|
||||||
const previousRef = useRef({ numericValue, value });
|
const previousRef = useRef({ numericValue, value });
|
||||||
const sequenceRef = useRef(0);
|
const sequenceRef = useRef(0);
|
||||||
@@ -31,8 +35,8 @@ export function RollingMetricValue({ numericValue, value }: RollingMetricValuePr
|
|||||||
|
|
||||||
useMetricLayoutEffect(() => {
|
useMetricLayoutEffect(() => {
|
||||||
const previous = previousRef.current;
|
const previous = previousRef.current;
|
||||||
if (previous.value === value && previous.numericValue === numericValue) return;
|
|
||||||
previousRef.current = { numericValue, value };
|
previousRef.current = { numericValue, value };
|
||||||
|
if (!shouldAnimateRollingMetric(previous.value, value)) return;
|
||||||
const direction = getRollingMetricDirection(previous.numericValue, numericValue);
|
const direction = getRollingMetricDirection(previous.numericValue, numericValue);
|
||||||
if (direction === "none") {
|
if (direction === "none") {
|
||||||
setTransition(null);
|
setTransition(null);
|
||||||
|
|||||||
@@ -117,8 +117,11 @@ export function getRemainingDownloadBytes(items: Iterable<DownloadItem>): { byte
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function formatRemainingDownloadBytes(summary: { bytes: number; unknownItems: number }): string {
|
export function formatRemainingDownloadBytes(summary: { bytes: number; unknownItems: number }): string {
|
||||||
if (summary.unknownItems <= 0) return humanSize(summary.bytes);
|
const value = summary.bytes >= 1024 ** 4
|
||||||
return summary.bytes > 0 ? `≥ ${humanSize(summary.bytes)}` : "Unbekannt";
|
? `${(summary.bytes / 1024 ** 4).toFixed(4)} TB`
|
||||||
|
: humanSize(summary.bytes);
|
||||||
|
if (summary.unknownItems <= 0) return value;
|
||||||
|
return summary.bytes > 0 ? `≥ ${value}` : "Unbekannt";
|
||||||
}
|
}
|
||||||
|
|
||||||
export function formatRemainingDownloadTooltip(summary: { bytes: number; unknownItems: number }): string {
|
export function formatRemainingDownloadTooltip(summary: { bytes: number; unknownItems: number }): string {
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ import {
|
|||||||
formatHosterLabel,
|
formatHosterLabel,
|
||||||
normalizeDownloadServiceLabel
|
normalizeDownloadServiceLabel
|
||||||
} from "../src/renderer/download-format";
|
} from "../src/renderer/download-format";
|
||||||
import { getRollingMetricDirection } from "../src/renderer/ui/RollingMetricValue";
|
import { getRollingMetricDirection, shouldAnimateRollingMetric } from "../src/renderer/ui/RollingMetricValue";
|
||||||
import { SlidingSelection } from "../src/renderer/ui/SlidingSelection";
|
import { SlidingSelection } from "../src/renderer/ui/SlidingSelection";
|
||||||
|
|
||||||
const now = new Date(2026, 7, 10, 12, 0, 0, 0).getTime();
|
const now = new Date(2026, 7, 10, 12, 0, 0, 0).getTime();
|
||||||
@@ -153,6 +153,11 @@ describe("Downloadtabellen-Spalten", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe("rollende Downloadkennzahlen", () => {
|
describe("rollende Downloadkennzahlen", () => {
|
||||||
|
it("does not animate raw byte changes while the visible value stays unchanged", () => {
|
||||||
|
expect(shouldAnimateRollingMetric("1.111 TB", "1.111 TB")).toBe(false);
|
||||||
|
expect(shouldAnimateRollingMetric("1.111 TB", "1.110 TB")).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
it("moves increasing values up and decreasing values down", () => {
|
it("moves increasing values up and decreasing values down", () => {
|
||||||
expect(getRollingMetricDirection(300, 600)).toBe("up");
|
expect(getRollingMetricDirection(300, 600)).toBe("up");
|
||||||
expect(getRollingMetricDirection(600, 300)).toBe("down");
|
expect(getRollingMetricDirection(600, 300)).toBe("down");
|
||||||
@@ -227,6 +232,10 @@ describe("Download-Gesamtgröße", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe("verbleibendes Downloadvolumen", () => {
|
describe("verbleibendes Downloadvolumen", () => {
|
||||||
|
it("shows a fourth TB decimal so fast downloads stay visibly responsive", () => {
|
||||||
|
expect(formatRemainingDownloadBytes({ bytes: Math.round(1.125 * 1024 ** 4), unknownItems: 0 })).toBe("1.1250 TB");
|
||||||
|
});
|
||||||
|
|
||||||
it("summiert nur offene bekannte Restbytes und klemmt überladene Fortschritte bei null", () => {
|
it("summiert nur offene bekannte Restbytes und klemmt überladene Fortschritte bei null", () => {
|
||||||
const items = [
|
const items = [
|
||||||
item("partial", "remaining", "downloading", { downloadedBytes: 750_000_000, totalBytes: 2_000_000_000 }),
|
item("partial", "remaining", "downloading", { downloadedBytes: 750_000_000, totalBytes: 2_000_000_000 }),
|
||||||
|
|||||||
Reference in New Issue
Block a user