Show cached data instantly instead of blocking on CLI refresh

Only show the loading overlay when no cached data exists for the
current period/provider. When stale data is available, display it
immediately while the background fetch runs. Also skip CLI calls
entirely when the cache is still fresh (within TTL), reducing
redundant subprocess invocations from the 30s LaunchAgent timer.
This commit is contained in:
AgentSeal 2026-04-28 18:09:13 +02:00
parent ce78ac52c1
commit daa292a998
2 changed files with 9 additions and 5 deletions

View file

@ -65,13 +65,13 @@ final class AppStore {
/// Switch to a period. Always fetches fresh data so the user never sees stale numbers.
func switchTo(period: Period) async {
selectedPeriod = period
await refresh(includeOptimize: true)
await refresh(includeOptimize: true, force: true)
}
/// Switch to a provider filter. Always fetches fresh data so the user never sees stale numbers.
func switchTo(provider: ProviderFilter) async {
selectedProvider = provider
await refresh(includeOptimize: true)
await refresh(includeOptimize: true, force: true)
}
private var inFlightKeys: Set<PayloadCacheKey> = []
@ -79,11 +79,15 @@ final class AppStore {
/// Refresh the currently selected (period, provider) combination. Guards against concurrent
/// fetches for the same key so a slow initial request can't overwrite a newer one that
/// finished first (which would show stale numbers the user has already moved past).
func refresh(includeOptimize: Bool) async {
/// When `force` is false (background timer), skips the CLI call if the cache is still fresh.
func refresh(includeOptimize: Bool, force: Bool = false) async {
let key = currentKey
if !force, cache[key]?.isFresh == true { return }
guard !inFlightKeys.contains(key) else { return }
inFlightKeys.insert(key)
isLoading = true
if cache[key] == nil {
isLoading = true
}
defer {
inFlightKeys.remove(key)
isLoading = false

View file

@ -397,7 +397,7 @@ struct FooterBar: View {
.fixedSize()
Button {
Task { await store.refresh(includeOptimize: true) }
Task { await store.refresh(includeOptimize: true, force: true) }
} label: {
Image(systemName: store.isLoading ? "arrow.triangle.2.circlepath" : "arrow.clockwise")
.font(.system(size: 11, weight: .medium))