mirror of
https://github.com/AgentSeal/codeburn.git
synced 2026-11-14 02:13:10 +00:00
Some checks are pending
CI / semgrep (push) Waiting to run
macOS Menubar CI / test (push) Waiting to run
Tests / test (22) (push) Waiting to run
Tests / test (22.13.0) (push) Waiting to run
Tests / test (24) (push) Waiting to run
Tests / test (26) (push) Waiting to run
Tests / test-platforms (macos-latest) (push) Waiting to run
Tests / test-platforms (windows-latest) (push) Waiting to run
Tests / desktop (push) Waiting to run
The catalog comparison matched specifier lists, so a key whose placeholders are all %@ passed even when the Chinese value bound the arguments into the wrong slots — the drift that shipped in three early-reset keys and was only caught by rendering real data bilingually (#1331). All 42 multi-argument keys in both tables now use positional specifiers (%1$@, %2$lld, ...); the parity check compares slot to verb so Chinese word order stays free while each slot keeps its type; a new test fails on any multi-argument key that is not positional. The source scanner closes its three expression gaps: ternary branches, concatenated literals, and let-bound literals passed by name. Text(verbatim:) stays the explicit opt-out; the four provider-name fallbacks the new rules surfaced in HeatmapSection route through the catalog as verbatim entries. Closes #1331
30 lines
1.3 KiB
Swift
30 lines
1.3 KiB
Swift
import Foundation
|
|
|
|
/// Countdown wording shared by the Capacity Dock, the popover quota rows and
|
|
/// the reset notices, plus Claude's fixed window lengths.
|
|
enum QuotaPacePresentation {
|
|
/// Claude's rate-limit windows are fixed lengths (the same values the
|
|
/// plan popover projects with), so they are validated durations.
|
|
static let claudeFiveHourSeconds = 5 * 3600
|
|
static let claudeSevenDaySeconds = 7 * 24 * 3600
|
|
|
|
/// "2d 3h" / "3h 20m" / "45m" / "<1m", mirroring the window column's own
|
|
/// countdown shape. Computed against the passed dates, never a hidden
|
|
/// wall clock, so fixtures stay deterministic.
|
|
static func countdownLabel(from now: Date, to date: Date) -> String {
|
|
countdownLabel(seconds: date.timeIntervalSince(now))
|
|
}
|
|
|
|
/// Countdown label for an already-computed interval (clamped at zero).
|
|
static func countdownLabel(seconds: TimeInterval) -> String {
|
|
let value = max(0, seconds)
|
|
if value < 60 { return L("<1m") }
|
|
let minutes = Int(value / 60)
|
|
let hours = minutes / 60
|
|
let days = hours / 24
|
|
// Same three keys the popover's reset countdown uses.
|
|
if days > 0 { return L("%1$lldd %2$lldh", days, hours % 24) }
|
|
if hours > 0 { return L("%1$lldh %2$lldm", hours, minutes % 60) }
|
|
return L("%lldm", minutes)
|
|
}
|
|
}
|