Skip to content
Open
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
15 changes: 10 additions & 5 deletions Sources/CodexBar/MenuCardView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -230,10 +230,12 @@ private struct UsageMenuCardHeaderView: View {
Text(self.model.providerName)
.font(.headline)
.fontWeight(.semibold)
Spacer()
Text(self.model.email)
.font(.subheadline)
.foregroundStyle(MenuHighlightStyle.secondary(self.isHighlighted))
if !self.model.email.isEmpty {
Spacer()
Text(self.model.email)
.font(.subheadline)
.foregroundStyle(MenuHighlightStyle.secondary(self.isHighlighted))
}
}
let subtitleAlignment: VerticalAlignment = self.model.subtitleStyle == .error ? .top : .firstTextBaseline
HStack(alignment: subtitleAlignment) {
Expand Down Expand Up @@ -666,6 +668,7 @@ extension UsageMenuCardView.Model {
let resetTimeDisplayStyle: ResetTimeDisplayStyle
let tokenCostUsageEnabled: Bool
let showOptionalCreditsAndExtraUsage: Bool
let showsHeaderEmail: Bool
let sourceLabel: String?
let kiloAutoMode: Bool
let hidePersonalInfo: Bool
Expand All @@ -689,6 +692,7 @@ extension UsageMenuCardView.Model {
resetTimeDisplayStyle: ResetTimeDisplayStyle,
tokenCostUsageEnabled: Bool,
showOptionalCreditsAndExtraUsage: Bool,
showsHeaderEmail: Bool = true,
sourceLabel: String? = nil,
kiloAutoMode: Bool = false,
hidePersonalInfo: Bool,
Expand All @@ -711,6 +715,7 @@ extension UsageMenuCardView.Model {
self.resetTimeDisplayStyle = resetTimeDisplayStyle
self.tokenCostUsageEnabled = tokenCostUsageEnabled
self.showOptionalCreditsAndExtraUsage = showOptionalCreditsAndExtraUsage
self.showsHeaderEmail = showsHeaderEmail
self.sourceLabel = sourceLabel
self.kiloAutoMode = kiloAutoMode
self.hidePersonalInfo = hidePersonalInfo
Expand Down Expand Up @@ -754,7 +759,7 @@ extension UsageMenuCardView.Model {
return UsageMenuCardView.Model(
provider: input.provider,
providerName: input.metadata.displayName,
email: redacted.email,
email: input.showsHeaderEmail ? redacted.email : "",
subtitleText: redacted.subtitleText,
subtitleStyle: subtitle.style,
planText: planText,
Expand Down
53 changes: 14 additions & 39 deletions Sources/CodexBar/StatusItemController+Menu.swift
Original file line number Diff line number Diff line change
Expand Up @@ -48,26 +48,6 @@ extension StatusItemController {
private static let maxOverviewProviders = SettingsStore.mergedOverviewProviderLimit
private static let overviewRowIdentifierPrefix = "overviewRow-"
private static let menuOpenRefreshDelay: Duration = .seconds(1.2)
private struct OpenAIWebMenuItems {
let hasUsageBreakdown: Bool
let hasCreditsHistory: Bool
let hasCostHistory: Bool
}

private struct TokenAccountMenuDisplay {
let provider: UsageProvider
let accounts: [ProviderTokenAccount]
let snapshots: [TokenAccountUsageSnapshot]
let activeIndex: Int
let showAll: Bool
let showSwitcher: Bool
}

private struct CodexAccountMenuDisplay {
let accounts: [CodexVisibleAccount]
let activeVisibleAccountID: String?
}

private func menuCardWidth(for providers: [UsageProvider], menu: NSMenu? = nil) -> CGFloat {
_ = menu
return Self.menuCardBaseWidth
Expand Down Expand Up @@ -232,6 +212,7 @@ extension StatusItemController {
currentProvider: currentProvider,
selectedProvider: selectedProvider,
menuWidth: menuWidth,
showsHeaderEmail: codexAccountDisplay == nil,
tokenAccountDisplay: tokenAccountDisplay,
openAIContext: openAIContext)
if isOverviewSelected {
Expand Down Expand Up @@ -296,6 +277,7 @@ extension StatusItemController {
currentProvider: currentProvider,
selectedProvider: provider,
menuWidth: menuWidth,
showsHeaderEmail: true,
tokenAccountDisplay: nil,
openAIContext: openAIContext)
let addedOpenAIWebItems = self.addMenuCards(to: menu, context: menuContext)
Expand All @@ -310,21 +292,6 @@ extension StatusItemController {
self.addActionableSections(descriptor.sections, to: menu, width: menuWidth)
}

private struct OpenAIWebContext {
let hasUsageBreakdown: Bool
let hasCreditsHistory: Bool
let hasCostHistory: Bool
let hasOpenAIWebMenuItems: Bool
}

private struct MenuCardContext {
let currentProvider: UsageProvider
let selectedProvider: UsageProvider?
let menuWidth: CGFloat
let tokenAccountDisplay: TokenAccountMenuDisplay?
let openAIContext: OpenAIWebContext
}

private func openAIWebContext(
currentProvider: UsageProvider,
showAllTokenAccounts: Bool) -> OpenAIWebContext
Expand Down Expand Up @@ -436,9 +403,12 @@ extension StatusItemController {
self.menuCardModel(
for: context.currentProvider,
snapshotOverride: accountSnapshot.snapshot,
errorOverride: accountSnapshot.error)
errorOverride: accountSnapshot.error,
showsHeaderEmail: context.showsHeaderEmail)
}
if cards.isEmpty, let model = self.menuCardModel(for: context.selectedProvider) {
if cards.isEmpty,
let model = self.menuCardModel(for: context.selectedProvider, showsHeaderEmail: context.showsHeaderEmail)
{
menu.addItem(self.makeMenuCardItem(
UsageMenuCardView(model: model, width: context.menuWidth),
id: "menuCard",
Expand All @@ -461,7 +431,10 @@ extension StatusItemController {
return false
}

guard let model = self.menuCardModel(for: context.selectedProvider) else { return false }
guard let model = self.menuCardModel(for: context.selectedProvider, showsHeaderEmail: context.showsHeaderEmail)
else {
return false
}
if context.openAIContext.hasOpenAIWebMenuItems {
let webItems = OpenAIWebMenuItems(
hasUsageBreakdown: context.openAIContext.hasUsageBreakdown,
Expand Down Expand Up @@ -1525,7 +1498,8 @@ extension StatusItemController {
func menuCardModel(
for provider: UsageProvider?,
snapshotOverride: UsageSnapshot? = nil,
errorOverride: String? = nil) -> UsageMenuCardView.Model?
errorOverride: String? = nil,
showsHeaderEmail: Bool = true) -> UsageMenuCardView.Model?
{
let target = provider ?? self.store.enabledProvidersForDisplay().first ?? .codex
let metadata = self.store.metadata(for: target)
Expand Down Expand Up @@ -1583,6 +1557,7 @@ extension StatusItemController {
resetTimeDisplayStyle: self.settings.resetTimeDisplayStyle,
tokenCostUsageEnabled: self.settings.isCostUsageEffectivelyEnabled(for: target),
showOptionalCreditsAndExtraUsage: self.settings.showOptionalCreditsAndExtraUsage,
showsHeaderEmail: showsHeaderEmail,
sourceLabel: sourceLabel,
kiloAutoMode: kiloAutoMode,
hidePersonalInfo: self.settings.hidePersonalInfo,
Expand Down
38 changes: 38 additions & 0 deletions Sources/CodexBar/StatusItemController+MenuTypes.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import AppKit
import CodexBarCore

struct OpenAIWebMenuItems {
let hasUsageBreakdown: Bool
let hasCreditsHistory: Bool
let hasCostHistory: Bool
}

struct TokenAccountMenuDisplay {
let provider: UsageProvider
let accounts: [ProviderTokenAccount]
let snapshots: [TokenAccountUsageSnapshot]
let activeIndex: Int
let showAll: Bool
let showSwitcher: Bool
}

struct CodexAccountMenuDisplay {
let accounts: [CodexVisibleAccount]
let activeVisibleAccountID: String?
}

struct OpenAIWebContext {
let hasUsageBreakdown: Bool
let hasCreditsHistory: Bool
let hasCostHistory: Bool
let hasOpenAIWebMenuItems: Bool
}

struct MenuCardContext {
let currentProvider: UsageProvider
let selectedProvider: UsageProvider?
let menuWidth: CGFloat
let showsHeaderEmail: Bool
let tokenAccountDisplay: TokenAccountMenuDisplay?
let openAIContext: OpenAIWebContext
}
51 changes: 51 additions & 0 deletions Tests/CodexBarTests/MenuCardHeaderVisibilityTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import CodexBarCore
import Foundation
import Testing
@testable import CodexBar

struct MenuCardHeaderVisibilityTests {
@Test
func `suppresses header email when requested`() throws {
let now = Date()
let identity = ProviderIdentitySnapshot(
providerID: .codex,
accountEmail: "codex@example.com",
accountOrganization: nil,
loginMethod: "Pro")
let snapshot = UsageSnapshot(
primary: RateWindow(
usedPercent: 0,
windowMinutes: 300,
resetsAt: now.addingTimeInterval(3000),
resetDescription: nil),
secondary: nil,
tertiary: nil,
updatedAt: now,
identity: identity)
let metadata = try #require(ProviderDefaults.metadata[.codex])

let model = UsageMenuCardView.Model.make(.init(
provider: .codex,
metadata: metadata,
snapshot: snapshot,
credits: nil,
creditsError: nil,
dashboard: nil,
dashboardError: nil,
tokenSnapshot: nil,
tokenError: nil,
account: AccountInfo(email: "codex@example.com", plan: "Pro"),
isRefreshing: false,
lastError: nil,
usageBarsShowUsed: false,
resetTimeDisplayStyle: .countdown,
tokenCostUsageEnabled: false,
showOptionalCreditsAndExtraUsage: true,
showsHeaderEmail: false,
hidePersonalInfo: false,
now: now))

#expect(model.email.isEmpty)
#expect(model.planText == "Pro")
}
}