Skip to content

Commit 5f9cfff

Browse files
committed
Refresh custom account labels
1 parent f8636cb commit 5f9cfff

3 files changed

Lines changed: 75 additions & 5 deletions

File tree

Sources/CodexBar/StatusItemController+IconObservation.swift

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ extension StatusItemController {
4747
let layoutCostSignature = showBrandPercent
4848
? self.storedMenuBarLayoutCostSignature(for: provider)
4949
: nil
50+
let layoutAccountSignature = showBrandPercent
51+
? self.storedMenuBarLayoutAccountSignature(for: provider, snapshot: snapshot)
52+
: nil
5053

5154
return [
5255
provider.rawValue,
@@ -60,9 +63,26 @@ extension StatusItemController {
6063
"refreshing=\(self.store.refreshingProviders.contains(provider) ? "1" : "0")",
6164
"text=\(displayText ?? "nil")",
6265
"layoutCost=\(layoutCostSignature ?? "nil")",
66+
"layoutAccount=\(layoutAccountSignature ?? "nil")",
6367
].joined(separator: "|")
6468
}
6569

70+
private func storedMenuBarLayoutAccountSignature(
71+
for provider: UsageProvider,
72+
snapshot: UsageSnapshot?)
73+
-> String?
74+
{
75+
let resolution = self.settings.menuBarLayoutResolution(for: provider)
76+
guard !resolution.usesLegacyRendering,
77+
resolution.layout.lines.joined().contains(.accountLabel),
78+
let accountLabel = self.menuBarLayoutAccountLabel(provider: provider, snapshot: snapshot)
79+
else { return nil }
80+
81+
var hasher = Hasher()
82+
hasher.combine(accountLabel)
83+
return String(hasher.finalize())
84+
}
85+
6686
private func storedMenuBarLayoutCostSignature(for provider: UsageProvider) -> String? {
6787
let resolution = self.settings.menuBarLayoutResolution(for: provider)
6888
guard !resolution.usesLegacyRendering else { return nil }

Sources/CodexBar/StatusItemController+MenuBarLayout.swift

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,7 @@ extension StatusItemController {
6262
.flatMap { UsagePaceText.weeklyDetail(provider: provider, pace: $0, now: now).rightLabel }
6363
let costStrings = self.menuBarLayoutCostStrings(provider: provider, now: now)
6464
let providerName = L(self.store.metadata(for: provider).displayName)
65-
let rawAccountLabel = snapshot?.accountEmail(for: provider)?
66-
.trimmingCharacters(in: .whitespacesAndNewlines)
67-
let accountLabel = self.settings.hidePersonalInfo || rawAccountLabel?.isEmpty != false
68-
? nil
69-
: rawAccountLabel
65+
let accountLabel = self.menuBarLayoutAccountLabel(provider: provider, snapshot: snapshot)
7066

7167
return MenuBarLayoutRenderData(
7268
iconKey: "\(provider.rawValue):\(warningFlash ? "warning" : "normal")",
@@ -80,6 +76,14 @@ extension StatusItemController {
8076
cost30d: costStrings.last30Days)
8177
}
8278

79+
func menuBarLayoutAccountLabel(provider: UsageProvider, snapshot: UsageSnapshot?) -> String? {
80+
let rawAccountLabel = snapshot?.accountEmail(for: provider)?
81+
.trimmingCharacters(in: .whitespacesAndNewlines)
82+
return self.settings.hidePersonalInfo || rawAccountLabel?.isEmpty != false
83+
? nil
84+
: rawAccountLabel
85+
}
86+
8387
func menuBarLayoutCostStrings(
8488
provider: UsageProvider,
8589
now: Date = .init())

Tests/CodexBarTests/StatusItemIconObservationSignatureTests.swift

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,52 @@ struct StatusItemIconObservationSignatureTests {
8686
suiteName: "StatusItemIconObservationSignatureTests-snapshot-metadata")
8787
defer { controller.releaseStatusItemsForTesting() }
8888

89+
let baseline = controller.storeIconObservationSignature()
90+
#expect(!baseline.contains("icon@example.com"))
91+
92+
store._setSnapshotForTesting(
93+
Self.makeSnapshot(
94+
provider: .codex,
95+
email: "rotated-account@example.com",
96+
updatedAt: Date(timeIntervalSince1970: 200)),
97+
provider: .codex)
98+
99+
let signature = controller.storeIconObservationSignature()
100+
101+
#expect(signature == baseline)
102+
#expect(!signature.contains("rotated-account@example.com"))
103+
}
104+
105+
@Test
106+
func `custom account label changes the store icon observation signature`() {
107+
let (_, store, controller) = self.makeController(
108+
suiteName: "StatusItemIconObservationSignatureTests-custom-account-label",
109+
menuBarLayout: MenuBarLayout(lines: [[.accountLabel]]))
110+
defer { controller.releaseStatusItemsForTesting() }
111+
112+
let baseline = controller.storeIconObservationSignature()
113+
#expect(!baseline.contains("icon@example.com"))
114+
115+
store._setSnapshotForTesting(
116+
Self.makeSnapshot(
117+
provider: .codex,
118+
email: "rotated-account@example.com",
119+
updatedAt: Date(timeIntervalSince1970: 200)),
120+
provider: .codex)
121+
122+
let signature = controller.storeIconObservationSignature()
123+
124+
#expect(signature != baseline)
125+
#expect(!signature.contains("rotated-account@example.com"))
126+
}
127+
128+
@Test
129+
func `hidden custom account label ignores account changes`() {
130+
let (settings, store, controller) = self.makeController(
131+
suiteName: "StatusItemIconObservationSignatureTests-hidden-custom-account-label",
132+
menuBarLayout: MenuBarLayout(lines: [[.accountLabel]]))
133+
defer { controller.releaseStatusItemsForTesting() }
134+
settings.hidePersonalInfo = true
89135
let baseline = controller.storeIconObservationSignature()
90136

91137
store._setSnapshotForTesting(

0 commit comments

Comments
 (0)