Skip to content

Commit 6702d55

Browse files
committed
Fix menubar provider view showing $0.00 after idle and refresh race condition
CLI timeout increased from 20s to 45s to handle cold file-cache latency on provider-specific queries. Loading overlay now appears when the all-provider payload confirms a provider has spend but its dedicated data hasn't loaded yet. Manual refresh (force: true) bypasses the in-flight guard so users can always re-fetch. Tab strip prefers the provider-specific payload cost when available so it stays in sync with the hero section.
1 parent 8cf68e7 commit 6702d55

4 files changed

Lines changed: 20 additions & 10 deletions

File tree

mac/Sources/CodeBurnMenubar/AppStore.swift

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -99,14 +99,10 @@ final class AppStore {
9999

100100
private var inFlightKeys: Set<PayloadCacheKey> = []
101101

102-
/// Refresh the currently selected (period, provider) combination. Guards against concurrent
103-
/// fetches for the same key so a slow initial request can't overwrite a newer one that
104-
/// finished first (which would show stale numbers the user has already moved past).
105-
/// When `force` is false (background timer), skips the CLI call if the cache is still fresh.
106102
func refresh(includeOptimize: Bool, force: Bool = false) async {
107103
let key = currentKey
108104
if !force, cache[key]?.isFresh == true { return }
109-
guard !inFlightKeys.contains(key) else { return }
105+
if !force, inFlightKeys.contains(key) { return }
110106
inFlightKeys.insert(key)
111107
let showedLoading = cache[key] == nil
112108
if showedLoading {

mac/Sources/CodeBurnMenubar/Data/DataClient.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import Foundation
66
/// Pipe file descriptors pinned forever.
77
private let maxPayloadBytes = 20 * 1024 * 1024
88
private let maxStderrBytes = 256 * 1024
9-
private let spawnTimeoutSeconds: UInt64 = 20
9+
private let spawnTimeoutSeconds: UInt64 = 45
1010

1111
enum DataClientError: Error {
1212
case spawn(String)

mac/Sources/CodeBurnMenubar/Views/AgentTabStrip.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ struct AgentTabStrip: View {
4646
private func cost(for filter: ProviderFilter) -> Double? {
4747
let data = periodAll
4848
if filter == .all { return data.current.cost }
49+
if filter == store.selectedProvider, store.hasCachedData {
50+
return store.payload.current.cost
51+
}
4952
let providers = Dictionary(
5053
data.current.providers.map { ($0.key.lowercased(), $0.value) },
5154
uniquingKeysWith: +

mac/Sources/CodeBurnMenubar/Views/MenuBarContent.swift

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ struct MenuBarContent: View {
4141
}
4242
}
4343

44-
if store.isLoading {
44+
if store.isLoading || (providerHasCostInAllPayload && !store.hasCachedData) {
4545
BurnLoadingOverlay(periodLabel: store.selectedPeriod.rawValue)
4646
.transition(.opacity)
4747
}
@@ -57,11 +57,22 @@ struct MenuBarContent: View {
5757
}
5858
}
5959

60-
/// True when a specific provider tab is selected and that provider has no spend in the
61-
/// currently selected period. The .all tab is exempt -- it always shows aggregated data.
6260
private var isFilteredEmpty: Bool {
6361
guard store.selectedProvider != .all else { return false }
64-
return store.payload.current.cost <= 0 && store.payload.current.calls == 0
62+
if store.payload.current.cost > 0 || store.payload.current.calls > 0 { return false }
63+
if providerHasCostInAllPayload { return false }
64+
return true
65+
}
66+
67+
private var providerHasCostInAllPayload: Bool {
68+
guard let allPayload = store.periodAllPayload else { return false }
69+
let providers = Dictionary(
70+
allPayload.current.providers.map { ($0.key.lowercased(), $0.value) },
71+
uniquingKeysWith: +
72+
)
73+
return store.selectedProvider.providerKeys.contains { key in
74+
(providers[key] ?? 0) > 0
75+
}
6576
}
6677

6778
/// Show the tab row whenever the CLI detected at least one AI coding tool installed

0 commit comments

Comments
 (0)