Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## 0.59.1 — Unreleased

### Fixed
- Codex accounts: honor Hide Personal Info in switcher labels and tooltips, redact embedded workspace emails, and preserve distinct account numbers in narrow menus (#3551). Thanks @zenibako!
- Codex spend: keep waiting history files ahead of repeated migration revisits so large histories can finish bounded catch-up, preserving stored rows and checkpoints (#3548, related to #3411). Thanks @SergeiNikolenko!

## 0.59.0 — 2026-09-10

### Highlights
Expand Down
40 changes: 40 additions & 0 deletions Sources/CodexBar/CodexAccountSwitcherLabeling.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import CodexBarCore
import Foundation

enum CodexAccountSwitcherLabeling {
static func ordinals(for accounts: [CodexVisibleAccount]) -> [String: Int] {
// The visible ID changes when a managed account becomes live; its persisted slot ID does not.
let ordered = accounts.sorted { lhs, rhs in
let left = lhs.storedAccountID?.uuidString ?? lhs.id
let right = rhs.storedAccountID?.uuidString ?? rhs.id
return left == right ? lhs.id < rhs.id : left < right
}
var ordinals: [String: Int] = [:]
for (index, account) in ordered.enumerated() {
ordinals[account.id] = index + 1
}
return ordinals
}

static func labels(for accounts: [CodexVisibleAccount], hidePersonalInfo: Bool) -> [String: String] {
let ordinals = self.ordinals(for: accounts)
return accounts.reduce(into: [:]) { labels, account in
labels[account.id] = self.label(
for: account, ordinal: ordinals[account.id], hidePersonalInfo: hidePersonalInfo)
}
}

static func accountLabel(ordinal: Int?) -> String {
L("Account %@", String(ordinal ?? 1))
}

static func label(for account: CodexVisibleAccount, ordinal: Int?, hidePersonalInfo: Bool) -> String {
guard hidePersonalInfo else { return account.menuDisplayName }
let number = self.accountLabel(ordinal: ordinal)
guard let workspace = PersonalInfoRedactor.redactEmails(in: account.menuWorkspaceLabel, isEnabled: true),
!workspace.isEmpty, !workspace.contains("@")
else { return number }
// A number on every private label also prevents collisions with user-supplied workspace names.
return "\(number) · \(workspace)"
}
}
Loading
Loading