From d64aa3d80c18813318b7fce84a8e61807b168039 Mon Sep 17 00:00:00 2001 From: fylorn <249551762+fylorn@users.noreply.github.com> Date: Wed, 28 Oct 2026 10:47:03 +0800 Subject: [PATCH] Round before picking the unit: storage usage and reset notices Settings > storage usage chose KB/MB from the raw byte count and rounded afterwards, so a value just under 1 MB or 1 GB read "1024 KB" or "1024 MB". It now rounds first and moves to the next unit, like size() and traffic() already do. Reset times in quota and key-limit notices truncated, so 1 h 59 min read "about 1 hour" while the menu bar said "2 h" for the same moment. They now round and then pick the unit, the same way resets_in() does. Co-Authored-By: Claude Opus 5.5 --- src-tauri/src/notices/rules.rs | 20 ++++++++++++-------- src-tauri/src/notices/tests.rs | 11 ++++++++++- src/settings/RetentionSection.tsx | 16 +++++++++++----- src/settings/retention.test.ts | 18 +++++++++++++++++- 4 files changed, 50 insertions(+), 15 deletions(-) diff --git a/src-tauri/src/notices/rules.rs b/src-tauri/src/notices/rules.rs index 680f9300..4a75a41a 100644 --- a/src-tauri/src/notices/rules.rs +++ b/src-tauri/src/notices/rules.rs @@ -1138,16 +1138,20 @@ fn window_label(w: &str) -> String { } /// 「,约 3 小时后重置」(英文是 ` and resets in about 3 hours`,接在句子中间)。 -/// 满一天按天说:每周的窗口离重置常常还有好几天,「约 150 小时」没法读 +/// 满一天按天说:每周的窗口离重置常常还有好几天,「约 150 小时」没法读。 +/// +/// **四舍五入、取整之后再定单位**,和菜单栏的 `resets_in` 一样:1 小时 59 分是「约 2 小时」, +/// 不是「约 1 小时」;59.5 分钟是「约 1 小时」,不是「约 60 分钟」 fn after(secs: u64) -> String { - let (n, unit, unit_en) = if secs >= 86_400 { - (secs / 86_400, "天", "day") - } else if secs >= 3600 { - (secs / 3600, "小时", "hour") - } else if secs >= 60 { - (secs / 60, "分钟", "minute") - } else { + let [m, h, d] = [60.0, 3600.0, 86_400.0].map(|unit| (secs as f64 / unit).round() as u64); + let (n, unit, unit_en) = if secs < 60 { return tr!(",即将重置", " and resets shortly").into(); + } else if m < 60 { + (m, "分钟", "minute") + } else if h < 24 { + (h, "小时", "hour") + } else { + (d, "天", "day") }; let plural = if n == 1 { "" } else { "s" }; tr!( diff --git a/src-tauri/src/notices/tests.rs b/src-tauri/src/notices/tests.rs index a0552631..73a20446 100644 --- a/src-tauri/src/notices/tests.rs +++ b/src-tauri/src/notices/tests.rs @@ -1473,11 +1473,20 @@ fn an_english_notice_reads_as_whole_sentences() { body("weekly", Some(3_600)) ); assert!( - body("7d", Some(90)).starts_with( + body("7d", Some(70)).starts_with( "The 7-day usage limit has been reached and resets in about 1 minute." ) ); assert!(body("weekly", Some(30)).contains("and resets shortly.")); + // 四舍五入、取整之后再定单位:1 小时 59 分说 2 小时,59.5 分钟说 1 小时,23.5 小时说 1 天 + for (secs, said) in [ + (7_140, "resets in about 2 hours."), + (3_570, "resets in about 1 hour."), + (84_600, "resets in about 1 day."), + ] { + let b = body("weekly", Some(secs)); + assert!(b.contains(said), "{secs}: {b}"); + } assert!(body("weekly", None).starts_with("The weekly usage limit has been reached. ")); let s = &rules::from_event(&tw_api::Event::ConfigRejected { diff --git a/src/settings/RetentionSection.tsx b/src/settings/RetentionSection.tsx index 7aa2da96..68d3d0dd 100644 --- a/src/settings/RetentionSection.tsx +++ b/src/settings/RetentionSection.tsx @@ -244,9 +244,15 @@ export function capText(n: number): string { return String(Number(g.toPrecision(3))); } -function bytes(n: number): string { - if (n >= GIB) return `${gib(n)} GB`; - if (n >= 1024 * 1024) return `${Math.round(n / (1024 * 1024))} MB`; - if (n >= 1024) return `${Math.round(n / 1024)} KB`; - return `${n} B`; +/** + * 占用写成 B / KB / MB / GB。**先取整再定单位**:差一点满 1 MB 的取整是 1024 KB,该写成 + * 「1 MB」,不是「1024 KB」;MB 到 GB 同理。导出给测试用。 + */ +export function bytes(n: number): string { + if (n < 1024) return `${n} B`; + const kb = Math.round(n / 1024); + if (kb < 1024) return `${kb} KB`; + const mb = Math.round(n / (1024 * 1024)); + if (mb < 1024) return `${mb} MB`; + return `${gib(n)} GB`; } diff --git a/src/settings/retention.test.ts b/src/settings/retention.test.ts index 8bfccb8a..841fc7d9 100644 --- a/src/settings/retention.test.ts +++ b/src/settings/retention.test.ts @@ -1,6 +1,6 @@ import { describe, expect, it } from "vitest"; import type { RetentionView } from "@/types"; -import { capText, checks, draftOf } from "./RetentionSection"; +import { bytes, capText, checks, draftOf } from "./RetentionSection"; const MIB = 1024 * 1024; const GIB = 1024 * MIB; @@ -45,3 +45,19 @@ describe("报文上限", () => { expect(checks({ ...saved, body_days: "0" }, saved).body_days).toBe(false); }); }); + +/** 占用的写法:取整进了位的,按下一档写 —— 不写「1024 KB」「1024 MB」 */ +describe("报文占用", () => { + it("按 B、KB、MB、GB", () => { + expect(bytes(512)).toBe("512 B"); + expect(bytes(300 * 1024)).toBe("300 KB"); + expect(bytes(412 * MIB)).toBe("412 MB"); + expect(bytes(Math.round(1.5 * GIB))).toBe("1.5 GB"); + }); + + it("进了位就按下一档写", () => { + expect(bytes(MIB - 100)).toBe("1 MB"); + expect(bytes(GIB - 100 * 1024)).toBe("1 GB"); + expect(bytes(MIB - 600)).toBe("1023 KB"); + }); +});