import AppKitimport CodexBarCoreimport QuartzCore extension StatusItemController { private static let loadingPercentEpsilon = 0.0001 private static let blinkActiveTickInterval: Duration = .milliseconds(75) private static let blinkIdleFallbackInterval: Duration = .seconds(1) static let loadingAnimationFPS: Double = 30.0 static let loadingAnimationPhaseIncrement: Double = 2.7 / StatusItemController.loadingAnimationFPS private static let loadingAnimationMaxContinuousDuration: TimeInterval = 30.0 func needsMenuBarIconAnimation() -> Bool { if self.shouldMergeIcons { let primaryProvider = self.primaryProviderForUnifiedIcon() return self.shouldAnimate(provider: primaryProvider) } return UsageProvider.allCases.contains { self.shouldAnimate(provider: $0) } } func updateBlinkingState() { #if DEBUG guard !self.isReleasedForTesting else { return } #endif // During the loading animation, blink ticks can overwrite the animated menu bar icon and cause flicker. if self.needsMenuBarIconAnimation() { self.stopBlinking() return } let blinkingEnabled = self.isBlinkingAllowed() // Use display list so merged-mode visibility stays consistent with shouldMergeIcons. let displayProviders = self.store.enabledProvidersForDisplay() let anyEnabled = !displayProviders.isEmpty || self.store.debugForceAnimation let anyVisible = UsageProvider.allCases.contains { self.isVisible($0) } let mergeIcons = self.shouldMergeIcons let shouldBlink = mergeIcons ? anyEnabled : anyVisible if blinkingEnabled, shouldBlink { if self.blinkTask == nil { self.seedBlinkStatesIfNeeded() self.blinkTask = Task { [weak self] in while !Task.isCancelled { let delay = await MainActor.run { self?.blinkTickSleepDuration(now: Date()) ?? Self.blinkIdleFallbackInterval } try? await Task.sleep(for: delay) await MainActor.run { self?.tickBlink() } } } } } else { self.stopBlinking() } } private func seedBlinkStatesIfNeeded() { let now = Date() for provider in UsageProvider.allCases where self.blinkStates[provider] == nil { self.blinkStates[provider] = BlinkState( nextBlink: now.addingTimeInterval(BlinkState.randomDelay())) } } private func stopBlinking() { self.blinkTask?.cancel() self.blinkTask = nil self.blinkAmounts.removeAll() let phase: Double? = self.needsMenuBarIconAnimation() ? self.animationPhase : nil if self.shouldMergeIcons { self.applyIcon(phase: phase) } else { for provider in UsageProvider.allCases { self.applyIcon(for: provider, phase: phase) } } } private func blinkTickSleepDuration(now: Date) -> Duration { let mergeIcons = self.shouldMergeIcons var nextWakeAt: Date? for provider in UsageProvider.allCases { let shouldRender = mergeIcons ? self.isEnabled(provider) : self.isVisible(provider) guard shouldRender, !self.shouldAnimate(provider: provider, mergeIcons: mergeIcons) else { continue } let state = self .blinkStates[provider] ?? BlinkState(nextBlink: now.addingTimeInterval(BlinkState.randomDelay())) if state.blinkStart != nil { return Self.blinkActiveTickInterval } let candidate: Date = state.pendingSecondStart ?? state.nextBlink if let current = nextWakeAt { if candidate < current { nextWakeAt = candidate } } else { nextWakeAt = candidate } } guard let nextWakeAt else { return Self.blinkIdleFallbackInterval } let delay = nextWakeAt.timeIntervalSince(now) if delay <= 0 { return Self.blinkActiveTickInterval } return .seconds(delay) } private func tickBlink(now: Date = .init()) { guard self.isBlinkingAllowed(at: now) else { self.stopBlinking() return } let blinkDuration: TimeInterval = 0.36 let doubleBlinkChance = 0.18 let doubleDelayRange: ClosedRange<TimeInterval> = 0.22...0.34 // Cache merge state once per tick to avoid repeated enabled-provider lookups. let mergeIcons = self.shouldMergeIcons for provider in UsageProvider.allCases { let shouldRender = mergeIcons ? self.isEnabled(provider) : self.isVisible(provider) guard shouldRender, !self.shouldAnimate(provider: provider, mergeIcons: mergeIcons) else { self.clearMotion(for: provider) continue } var state = self .blinkStates[provider] ?? BlinkState(nextBlink: now.addingTimeInterval(BlinkState.randomDelay())) if let pendingSecond = state.pendingSecondStart, now >= pendingSecond { state.blinkStart = now state.pendingSecondStart = nil } if let start = state.blinkStart { let elapsed = now.timeIntervalSince(start) if elapsed >= blinkDuration { state.blinkStart = nil if let pending = state.pendingSecondStart, now < pending { // Wait for the planned double-blink. } else { state.pendingSecondStart = nil state.nextBlink = now.addingTimeInterval(BlinkState.randomDelay()) } self.clearMotion(for: provider) } else { let progress = max(0, min(elapsed / blinkDuration, 1)) let symmetric = progress < 0.5 ? progress * 2 : (1 - progress) * 2 let eased = pow(symmetric, 2.2) // slightly punchier than smoothstep self.assignMotion(amount: CGFloat(eased), for: provider, effect: state.effect) } } else if now >= state.nextBlink { state.blinkStart = now state.effect = self.randomEffect(for: provider) if state.effect == .blink, Double.random(in: 0...1) < doubleBlinkChance { state.pendingSecondStart = now.addingTimeInterval( Double.random(in: doubleDelayRange)) } self.clearMotion(for: provider) } else { self.clearMotion(for: provider) } self.blinkStates[provider] = state if !mergeIcons { self.applyIcon(for: provider, phase: nil) } } if mergeIcons { self.applyIcon(phase: nil) } } private func blinkAmount(for provider: UsageProvider) -> CGFloat { guard self.isBlinkingAllowed() else { return 0 } return self.blinkAmounts[provider] ?? 0 } private func wiggleAmount(for provider: UsageProvider) -> CGFloat { guard self.isBlinkingAllowed() else { return 0 } return self.wiggleAmounts[provider] ?? 0 } private func tiltAmount(for provider: UsageProvider) -> CGFloat { guard self.isBlinkingAllowed() else { return 0 } return self.tiltAmounts[provider] ?? 0 } private func assignMotion(amount: CGFloat, for provider: UsageProvider, effect: MotionEffect) { switch effect { case .blink: self.blinkAmounts[provider] = amount self.wiggleAmounts[provider] = 0 self.tiltAmounts[provider] = 0 case .wiggle: self.wiggleAmounts[provider] = amount self.blinkAmounts[provider] = 0 self.tiltAmounts[provider] = 0 case .tilt: self.tiltAmounts[provider] = amount self.blinkAmounts[provider] = 0 self.wiggleAmounts[provider] = 0 } } private func clearMotion(for provider: UsageProvider) { self.blinkAmounts[provider] = 0 self.wiggleAmounts[provider] = 0 self.tiltAmounts[provider] = 0 } private func randomEffect(for provider: UsageProvider) -> MotionEffect { if provider == .claude { Bool.random() ? .blink : .wiggle } else { Bool.random() ? .blink : .tilt } } private func isBlinkingAllowed(at date: Date = .init()) -> Bool { if self.settings.randomBlinkEnabled { return true } if let until = self.blinkForceUntil, until > date { return true } self.blinkForceUntil = nil return false } @discardableResult func applyIcon( phase: Double?, bypassMergedMenuTrackingDeferral: Bool = false) -> Bool { guard let button = self.statusItem.button else { return false } if !bypassMergedMenuTrackingDeferral, self.deferMergedIconRenderDuringMenuTrackingIfNeeded() { return true } let style = self.store.iconStyle let showUsed = self.settings.usageBarsShowUsed let showBrandPercent = self.settings.menuBarShowsBrandIconWithPercent let primaryProvider = self.primaryProviderForUnifiedIcon() let resolverStyle = self.store.style(for: primaryProvider) let snapshot = self.store.snapshot(for: primaryProvider) let warningFlash = self.quotaWarningFlashActive(provider: primaryProvider) // IconRenderer treats these values as a left-to-right "progress fill" percentage; depending on the // user setting we pass either "percent left" or "percent used". let resolved = snapshot.map { IconRemainingResolver.resolvedPercents( snapshot: $0, style: resolverStyle, showUsed: showUsed, renderingStyle: style, secondaryOverrideWindowID: self.settings.copilotIconSecondaryWindowOverrideID(snapshot: $0)) } var primary = resolved?.primary var weekly = resolved?.secondary var credits = self.menuBarCreditsRemainingForIcon(provider: primaryProvider, snapshot: snapshot) var stale = self.store.isStale(provider: primaryProvider) var morphProgress: Double? let needsAnimation = self.needsMenuBarIconAnimation() if let phase, needsAnimation { var pattern = self.animationPattern if style == .combined, pattern == .unbraid { pattern = .cylon } if pattern == .unbraid { morphProgress = pattern.value(phase: phase) / 100 primary = nil weekly = nil credits = nil stale = false } else { // Keep loading animation layout stable: IconRenderer uses `weeklyRemaining > 0` to switch layouts, // so hitting an exact 0 would flip between "normal" and "weekly exhausted" rendering. primary = max(pattern.value(phase: phase), Self.loadingPercentEpsilon) weekly = max( pattern.value(phase: phase + pattern.secondaryOffset), Self.loadingPercentEpsilon) credits = nil stale = false } } let blink: CGFloat = style == .combined ? 0 : self.blinkAmount(for: primaryProvider) let wiggle: CGFloat = style == .combined ? 0 : self.wiggleAmount(for: primaryProvider) let tilt: CGFloat = style == .combined ? 0 : self.tiltAmount(for: primaryProvider) * .pi / 28 let statusIndicator = self.store.statusIndicator(for: primaryProvider) if showBrandPercent, let brand = ProviderBrandIcon.image(for: primaryProvider) { let displayText = self.menuBarDisplayText(for: primaryProvider, snapshot: snapshot) let signature = [ "mode=brandPercent", "provider=\(primaryProvider.rawValue)", "style=\(String(describing: style))", "primary=\(Self.iconSignatureValue(primary))", "weekly=\(Self.iconSignatureValue(weekly))", "credits=\(Self.iconSignatureValue(credits))", "stale=\(stale ? "1" : "0")", "status=\(statusIndicator.rawValue)", "text=\(displayText ?? "nil")", "warningFlash=\(warningFlash ? "1" : "0")", "anim=\(needsAnimation ? "1" : "0")", "hideCritters=\(self.settings.menuBarHidesCritters ? "1" : "0")", ].joined(separator: "|") if self.shouldSkipMergedIconRender(signature) { // AppKit can lose button title/image-position state independently of the cached render signature. // Keep the cheap title path self-healing even when the icon image itself can be skipped. self.setButtonTitle(displayText, for: button) self.noteIconPerfRender(skipped: true) return true } self.setButtonImage( warningFlash ? Self.quotaWarningFlashImage(base: brand) : brand, for: button) self.setButtonTitle(displayText, for: button) self.noteIconPerfRender(skipped: false) return false } self.setButtonTitle(nil, for: button) if let morphProgress { let signature = [ "mode=morph", "provider=\(primaryProvider.rawValue)", "style=\(String(describing: style))", "morph=\(Self.iconSignatureValue(morphProgress))", "status=\(statusIndicator.rawValue)", "warningFlash=\(warningFlash ? "1" : "0")", "anim=\(needsAnimation ? "1" : "0")", "hideCritters=\(self.settings.menuBarHidesCritters ? "1" : "0")", ].joined(separator: "|") if self.shouldSkipMergedIconRender(signature) { self.noteIconPerfRender(skipped: true) return true } let image = IconRenderer.makeMorphIcon( progress: morphProgress, style: style, hideCritters: self.settings.menuBarHidesCritters) self.setButtonImage( warningFlash ? Self.quotaWarningFlashImage(base: image) : image, for: button) } else { let signature = [ "mode=icon", "provider=\(primaryProvider.rawValue)", "style=\(String(describing: style))", "primary=\(Self.iconSignatureValue(primary))", "weekly=\(Self.iconSignatureValue(weekly))", "credits=\(Self.iconSignatureValue(credits))", "stale=\(stale ? "1" : "0")", "status=\(statusIndicator.rawValue)", "blink=\(Self.iconSignatureValue(Double(blink)))", "wiggle=\(Self.iconSignatureValue(Double(wiggle)))", "tilt=\(Self.iconSignatureValue(Double(tilt)))", "warningFlash=\(warningFlash ? "1" : "0")", "anim=\(needsAnimation ? "1" : "0")", "hideCritters=\(self.settings.menuBarHidesCritters ? "1" : "0")", ].joined(separator: "|") if self.shouldSkipMergedIconRender(signature) { self.noteIconPerfRender(skipped: true) return true } let image = IconRenderer.makeIcon( primaryRemaining: primary, weeklyRemaining: weekly, creditsRemaining: credits, stale: stale, style: style, blink: blink, wiggle: wiggle, tilt: tilt, statusIndicator: statusIndicator, hideCritters: self.settings.menuBarHidesCritters) self.setButtonImage( warningFlash ? Self.quotaWarningFlashImage(base: image) : image, for: button) } self.noteIconPerfRender(skipped: false) return false } private func deferMergedIconRenderDuringMenuTrackingIfNeeded() -> Bool { guard self.shouldMergeIcons, self.isMergedMenuOpen else { return false } self.deferredMergedIconRenderAfterTracking = true self.noteIconPerfRender(skipped: true) return true } func applyDeferredMergedIconRenderAfterTrackingIfNeeded() { guard self.deferredMergedIconRenderAfterTracking else { return } guard self.shouldMergeIcons else { self.deferredMergedIconRenderAfterTracking = false return } guard !self.isMergedMenuOpen else { return } self.deferredMergedIconRenderAfterTracking = false let phase: Double? = self.animationDriver == nil ? nil : self.animationPhase self.applyIcon(phase: phase) } private func shouldSkipMergedIconRender(_ signature: String) -> Bool { guard self.shouldMergeIcons else { self.lastAppliedMergedIconRenderSignature = signature return false } if self.lastAppliedMergedIconRenderSignature == signature { return true } self.lastAppliedMergedIconRenderSignature = signature return false } private func shouldSkipProviderIconRender(provider: UsageProvider, signature: String) -> Bool { if self.lastAppliedProviderIconRenderSignatures[provider] == signature { return true } self.lastAppliedProviderIconRenderSignatures[provider] = signature return false } @discardableResult func applyIcon(for provider: UsageProvider, phase: Double?) -> Bool { guard let button = self.statusItems[provider]?.button else { return false } let snapshot = self.store.snapshot(for: provider) // IconRenderer treats these values as a left-to-right "progress fill" percentage; depending on the // user setting we pass either "percent left" or "percent used". let showUsed = self.settings.usageBarsShowUsed let showBrandPercent = self.settings.menuBarShowsBrandIconWithPercent let style: IconStyle = self.store.style(for: provider) let warningFlash = self.quotaWarningFlashActive(provider: provider) if showBrandPercent, let brand = ProviderBrandIcon.image(for: provider) { let displayText = self.menuBarDisplayText(for: provider, snapshot: snapshot) let signature = [ "mode=brandPercent", "provider=\(provider.rawValue)", "style=\(String(describing: style))", "text=\(displayText ?? "nil")", "warningFlash=\(warningFlash ? "1" : "0")", ].joined(separator: "|") if self.shouldSkipProviderIconRender(provider: provider, signature: signature) { self.noteIconPerfRender(skipped: true) return true } self.setButtonImage( warningFlash ? Self.quotaWarningFlashImage(base: brand) : brand, for: button) self.setButtonTitle(displayText, for: button) self.noteIconPerfRender(skipped: false) return false } self.setButtonTitle(nil, for: button) // OpenRouter always gets a meter here — the brand-logo fallback was removed on purpose. let resolved = snapshot.map { IconRemainingResolver.resolvedPercents( snapshot: $0, style: style, showUsed: showUsed, secondaryOverrideWindowID: self.settings.copilotIconSecondaryWindowOverrideID(snapshot: $0)) } var primary = resolved?.primary var weekly = resolved?.secondary var credits = self.menuBarCreditsRemainingForIcon(provider: provider, snapshot: snapshot) var stale = self.store.isStale(provider: provider) var morphProgress: Double? if let phase, self.shouldAnimate(provider: provider) { var pattern = self.animationPattern if provider == .claude, pattern == .unbraid { pattern = .cylon } if pattern == .unbraid { morphProgress = pattern.value(phase: phase) / 100 primary = nil weekly = nil credits = nil stale = false } else { // Keep loading animation layout stable: IconRenderer switches layouts at `weeklyRemaining == 0`. primary = max(pattern.value(phase: phase), Self.loadingPercentEpsilon) weekly = max( pattern.value(phase: phase + pattern.secondaryOffset), Self.loadingPercentEpsilon) credits = nil stale = false } } let isLoading = phase != nil && self.shouldAnimate(provider: provider)Lines 1–500 of 1207. Load more
import AppKit import CodexBarCore import QuartzCore extension StatusItemController { private static let loadingPercentEpsilon = 0.0001 private static let blinkActiveTickInterval: Duration = .milliseconds(75) private static let blinkIdleFallbackInterval: Duration = .seconds(1) static let loadingAnimationFPS: Double = 30.0 static let loadingAnimationPhaseIncrement: Double = 2.7 / StatusItemController.loadingAnimationFPS private static let loadingAnimationMaxContinuousDuration: TimeInterval = 30.0 func needsMenuBarIconAnimation() -> Bool { if self.shouldMergeIcons { let primaryProvider = self.primaryProviderForUnifiedIcon() return self.shouldAnimate(provider: primaryProvider) } return UsageProvider.allCases.contains { self.shouldAnimate(provider: $0) } } func updateBlinkingState() { #if DEBUG guard !self.isReleasedForTesting else { return } #endif // During the loading animation, blink ticks can overwrite the animated menu bar icon and cause flicker. if self.needsMenuBarIconAnimation() { self.stopBlinking() return } let blinkingEnabled = self.isBlinkingAllowed() // Use display list so merged-mode visibility stays consistent with shouldMergeIcons. let displayProviders = self.store.enabledProvidersForDisplay() let anyEnabled = !displayProviders.isEmpty || self.store.debugForceAnimation let anyVisible = UsageProvider.allCases.contains { self.isVisible($0) } let mergeIcons = self.shouldMergeIcons let shouldBlink = mergeIcons ? anyEnabled : anyVisible if blinkingEnabled, shouldBlink { if self.blinkTask == nil { self.seedBlinkStatesIfNeeded() self.blinkTask = Task { [weak self] in while !Task.isCancelled { let delay = await MainActor.run { self?.blinkTickSleepDuration(now: Date()) ?? Self.blinkIdleFallbackInterval } try? await Task.sleep(for: delay) await MainActor.run { self?.tickBlink() } } } } } else { self.stopBlinking() } } private func seedBlinkStatesIfNeeded() { let now = Date() for provider in UsageProvider.allCases where self.blinkStates[provider] == nil { self.blinkStates[provider] = BlinkState( nextBlink: now.addingTimeInterval(BlinkState.randomDelay())) } } private func stopBlinking() { self.blinkTask?.cancel() self.blinkTask = nil self.blinkAmounts.removeAll() let phase: Double? = self.needsMenuBarIconAnimation() ? self.animationPhase : nil if self.shouldMergeIcons { self.applyIcon(phase: phase) } else { for provider in UsageProvider.allCases { self.applyIcon(for: provider, phase: phase) } } } private func blinkTickSleepDuration(now: Date) -> Duration { let mergeIcons = self.shouldMergeIcons var nextWakeAt: Date? for provider in UsageProvider.allCases { let shouldRender = mergeIcons ? self.isEnabled(provider) : self.isVisible(provider) guard shouldRender, !self.shouldAnimate(provider: provider, mergeIcons: mergeIcons) else { continue } let state = self .blinkStates[provider] ?? BlinkState(nextBlink: now.addingTimeInterval(BlinkState.randomDelay())) if state.blinkStart != nil { return Self.blinkActiveTickInterval } let candidate: Date = state.pendingSecondStart ?? state.nextBlink if let current = nextWakeAt { if candidate < current { nextWakeAt = candidate } } else { nextWakeAt = candidate } } guard let nextWakeAt else { return Self.blinkIdleFallbackInterval } let delay = nextWakeAt.timeIntervalSince(now) if delay <= 0 { return Self.blinkActiveTickInterval } return .seconds(delay) } private func tickBlink(now: Date = .init()) { guard self.isBlinkingAllowed(at: now) else { self.stopBlinking() return } let blinkDuration: TimeInterval = 0.36 let doubleBlinkChance = 0.18 let doubleDelayRange: ClosedRange<TimeInterval> = 0.22...0.34 // Cache merge state once per tick to avoid repeated enabled-provider lookups. let mergeIcons = self.shouldMergeIcons for provider in UsageProvider.allCases { let shouldRender = mergeIcons ? self.isEnabled(provider) : self.isVisible(provider) guard shouldRender, !self.shouldAnimate(provider: provider, mergeIcons: mergeIcons) else { self.clearMotion(for: provider) continue } var state = self .blinkStates[provider] ?? BlinkState(nextBlink: now.addingTimeInterval(BlinkState.randomDelay())) if let pendingSecond = state.pendingSecondStart, now >= pendingSecond { state.blinkStart = now state.pendingSecondStart = nil } if let start = state.blinkStart { let elapsed = now.timeIntervalSince(start) if elapsed >= blinkDuration { state.blinkStart = nil if let pending = state.pendingSecondStart, now < pending { // Wait for the planned double-blink. } else { state.pendingSecondStart = nil state.nextBlink = now.addingTimeInterval(BlinkState.randomDelay()) } self.clearMotion(for: provider) } else { let progress = max(0, min(elapsed / blinkDuration, 1)) let symmetric = progress < 0.5 ? progress * 2 : (1 - progress) * 2 let eased = pow(symmetric, 2.2) // slightly punchier than smoothstep self.assignMotion(amount: CGFloat(eased), for: provider, effect: state.effect) } } else if now >= state.nextBlink { state.blinkStart = now state.effect = self.randomEffect(for: provider) if state.effect == .blink, Double.random(in: 0...1) < doubleBlinkChance { state.pendingSecondStart = now.addingTimeInterval( Double.random(in: doubleDelayRange)) } self.clearMotion(for: provider) } else { self.clearMotion(for: provider) } self.blinkStates[provider] = state if !mergeIcons { self.applyIcon(for: provider, phase: nil) } } if mergeIcons { self.applyIcon(phase: nil) } } private func blinkAmount(for provider: UsageProvider) -> CGFloat { guard self.isBlinkingAllowed() else { return 0 } return self.blinkAmounts[provider] ?? 0 } private func wiggleAmount(for provider: UsageProvider) -> CGFloat { guard self.isBlinkingAllowed() else { return 0 } return self.wiggleAmounts[provider] ?? 0 } private func tiltAmount(for provider: UsageProvider) -> CGFloat { guard self.isBlinkingAllowed() else { return 0 } return self.tiltAmounts[provider] ?? 0 } private func assignMotion(amount: CGFloat, for provider: UsageProvider, effect: MotionEffect) { switch effect { case .blink: self.blinkAmounts[provider] = amount self.wiggleAmounts[provider] = 0 self.tiltAmounts[provider] = 0 case .wiggle: self.wiggleAmounts[provider] = amount self.blinkAmounts[provider] = 0 self.tiltAmounts[provider] = 0 case .tilt: self.tiltAmounts[provider] = amount self.blinkAmounts[provider] = 0 self.wiggleAmounts[provider] = 0 } } private func clearMotion(for provider: UsageProvider) { self.blinkAmounts[provider] = 0 self.wiggleAmounts[provider] = 0 self.tiltAmounts[provider] = 0 } private func randomEffect(for provider: UsageProvider) -> MotionEffect { if provider == .claude { Bool.random() ? .blink : .wiggle } else { Bool.random() ? .blink : .tilt } } private func isBlinkingAllowed(at date: Date = .init()) -> Bool { if self.settings.randomBlinkEnabled { return true } if let until = self.blinkForceUntil, until > date { return true } self.blinkForceUntil = nil return false } @discardableResult func applyIcon( phase: Double?, bypassMergedMenuTrackingDeferral: Bool = false) -> Bool { guard let button = self.statusItem.button else { return false } if !bypassMergedMenuTrackingDeferral, self.deferMergedIconRenderDuringMenuTrackingIfNeeded() { return true } let style = self.store.iconStyle let showUsed = self.settings.usageBarsShowUsed let showBrandPercent = self.settings.menuBarShowsBrandIconWithPercent let primaryProvider = self.primaryProviderForUnifiedIcon() let resolverStyle = self.store.style(for: primaryProvider) let snapshot = self.store.snapshot(for: primaryProvider) let warningFlash = self.quotaWarningFlashActive(provider: primaryProvider) // IconRenderer treats these values as a left-to-right "progress fill" percentage; depending on the // user setting we pass either "percent left" or "percent used". let resolved = snapshot.map { IconRemainingResolver.resolvedPercents( snapshot: $0, style: resolverStyle, showUsed: showUsed, renderingStyle: style, secondaryOverrideWindowID: self.settings.copilotIconSecondaryWindowOverrideID(snapshot: $0)) } var primary = resolved?.primary var weekly = resolved?.secondary var credits = self.menuBarCreditsRemainingForIcon(provider: primaryProvider, snapshot: snapshot) var stale = self.store.isStale(provider: primaryProvider) var morphProgress: Double? let needsAnimation = self.needsMenuBarIconAnimation() if let phase, needsAnimation { var pattern = self.animationPattern if style == .combined, pattern == .unbraid { pattern = .cylon } if pattern == .unbraid { morphProgress = pattern.value(phase: phase) / 100 primary = nil weekly = nil credits = nil stale = false } else { // Keep loading animation layout stable: IconRenderer uses `weeklyRemaining > 0` to switch layouts, // so hitting an exact 0 would flip between "normal" and "weekly exhausted" rendering. primary = max(pattern.value(phase: phase), Self.loadingPercentEpsilon) weekly = max( pattern.value(phase: phase + pattern.secondaryOffset), Self.loadingPercentEpsilon) credits = nil stale = false } } let blink: CGFloat = style == .combined ? 0 : self.blinkAmount(for: primaryProvider) let wiggle: CGFloat = style == .combined ? 0 : self.wiggleAmount(for: primaryProvider) let tilt: CGFloat = style == .combined ? 0 : self.tiltAmount(for: primaryProvider) * .pi / 28 let statusIndicator = self.store.statusIndicator(for: primaryProvider) if showBrandPercent, let brand = ProviderBrandIcon.image(for: primaryProvider) { let displayText = self.menuBarDisplayText(for: primaryProvider, snapshot: snapshot) let signature = [ "mode=brandPercent", "provider=\(primaryProvider.rawValue)", "style=\(String(describing: style))", "primary=\(Self.iconSignatureValue(primary))", "weekly=\(Self.iconSignatureValue(weekly))", "credits=\(Self.iconSignatureValue(credits))", "stale=\(stale ? "1" : "0")", "status=\(statusIndicator.rawValue)", "text=\(displayText ?? "nil")", "warningFlash=\(warningFlash ? "1" : "0")", "anim=\(needsAnimation ? "1" : "0")", "hideCritters=\(self.settings.menuBarHidesCritters ? "1" : "0")", ].joined(separator: "|") if self.shouldSkipMergedIconRender(signature) { // AppKit can lose button title/image-position state independently of the cached render signature. // Keep the cheap title path self-healing even when the icon image itself can be skipped. self.setButtonTitle(displayText, for: button) self.noteIconPerfRender(skipped: true) return true } self.setButtonImage( warningFlash ? Self.quotaWarningFlashImage(base: brand) : brand, for: button) self.setButtonTitle(displayText, for: button) self.noteIconPerfRender(skipped: false) return false } self.setButtonTitle(nil, for: button) if let morphProgress { let signature = [ "mode=morph", "provider=\(primaryProvider.rawValue)", "style=\(String(describing: style))", "morph=\(Self.iconSignatureValue(morphProgress))", "status=\(statusIndicator.rawValue)", "warningFlash=\(warningFlash ? "1" : "0")", "anim=\(needsAnimation ? "1" : "0")", "hideCritters=\(self.settings.menuBarHidesCritters ? "1" : "0")", ].joined(separator: "|") if self.shouldSkipMergedIconRender(signature) { self.noteIconPerfRender(skipped: true) return true } let image = IconRenderer.makeMorphIcon( progress: morphProgress, style: style, hideCritters: self.settings.menuBarHidesCritters) self.setButtonImage( warningFlash ? Self.quotaWarningFlashImage(base: image) : image, for: button) } else { let signature = [ "mode=icon", "provider=\(primaryProvider.rawValue)", "style=\(String(describing: style))", "primary=\(Self.iconSignatureValue(primary))", "weekly=\(Self.iconSignatureValue(weekly))", "credits=\(Self.iconSignatureValue(credits))", "stale=\(stale ? "1" : "0")", "status=\(statusIndicator.rawValue)", "blink=\(Self.iconSignatureValue(Double(blink)))", "wiggle=\(Self.iconSignatureValue(Double(wiggle)))", "tilt=\(Self.iconSignatureValue(Double(tilt)))", "warningFlash=\(warningFlash ? "1" : "0")", "anim=\(needsAnimation ? "1" : "0")", "hideCritters=\(self.settings.menuBarHidesCritters ? "1" : "0")", ].joined(separator: "|") if self.shouldSkipMergedIconRender(signature) { self.noteIconPerfRender(skipped: true) return true } let image = IconRenderer.makeIcon( primaryRemaining: primary, weeklyRemaining: weekly, creditsRemaining: credits, stale: stale, style: style, blink: blink, wiggle: wiggle, tilt: tilt, statusIndicator: statusIndicator, hideCritters: self.settings.menuBarHidesCritters) self.setButtonImage( warningFlash ? Self.quotaWarningFlashImage(base: image) : image, for: button) } self.noteIconPerfRender(skipped: false) return false } private func deferMergedIconRenderDuringMenuTrackingIfNeeded() -> Bool { guard self.shouldMergeIcons, self.isMergedMenuOpen else { return false } self.deferredMergedIconRenderAfterTracking = true self.noteIconPerfRender(skipped: true) return true } func applyDeferredMergedIconRenderAfterTrackingIfNeeded() { guard self.deferredMergedIconRenderAfterTracking else { return } guard self.shouldMergeIcons else { self.deferredMergedIconRenderAfterTracking = false return } guard !self.isMergedMenuOpen else { return } self.deferredMergedIconRenderAfterTracking = false let phase: Double? = self.animationDriver == nil ? nil : self.animationPhase self.applyIcon(phase: phase) } private func shouldSkipMergedIconRender(_ signature: String) -> Bool { guard self.shouldMergeIcons else { self.lastAppliedMergedIconRenderSignature = signature return false } if self.lastAppliedMergedIconRenderSignature == signature { return true } self.lastAppliedMergedIconRenderSignature = signature return false } private func shouldSkipProviderIconRender(provider: UsageProvider, signature: String) -> Bool { if self.lastAppliedProviderIconRenderSignatures[provider] == signature { return true } self.lastAppliedProviderIconRenderSignatures[provider] = signature return false } @discardableResult func applyIcon(for provider: UsageProvider, phase: Double?) -> Bool { guard let button = self.statusItems[provider]?.button else { return false } let snapshot = self.store.snapshot(for: provider) // IconRenderer treats these values as a left-to-right "progress fill" percentage; depending on the // user setting we pass either "percent left" or "percent used". let showUsed = self.settings.usageBarsShowUsed let showBrandPercent = self.settings.menuBarShowsBrandIconWithPercent let style: IconStyle = self.store.style(for: provider) let warningFlash = self.quotaWarningFlashActive(provider: provider) if showBrandPercent, let brand = ProviderBrandIcon.image(for: provider) { let displayText = self.menuBarDisplayText(for: provider, snapshot: snapshot) let signature = [ "mode=brandPercent", "provider=\(provider.rawValue)", "style=\(String(describing: style))", "text=\(displayText ?? "nil")", "warningFlash=\(warningFlash ? "1" : "0")", ].joined(separator: "|") if self.shouldSkipProviderIconRender(provider: provider, signature: signature) { self.noteIconPerfRender(skipped: true) return true } self.setButtonImage( warningFlash ? Self.quotaWarningFlashImage(base: brand) : brand, for: button) self.setButtonTitle(displayText, for: button) self.noteIconPerfRender(skipped: false) return false } self.setButtonTitle(nil, for: button) // OpenRouter always gets a meter here — the brand-logo fallback was removed on purpose. let resolved = snapshot.map { IconRemainingResolver.resolvedPercents( snapshot: $0, style: style, showUsed: showUsed, secondaryOverrideWindowID: self.settings.copilotIconSecondaryWindowOverrideID(snapshot: $0)) } var primary = resolved?.primary var weekly = resolved?.secondary var credits = self.menuBarCreditsRemainingForIcon(provider: provider, snapshot: snapshot) var stale = self.store.isStale(provider: provider) var morphProgress: Double? if let phase, self.shouldAnimate(provider: provider) { var pattern = self.animationPattern if provider == .claude, pattern == .unbraid { pattern = .cylon } if pattern == .unbraid { morphProgress = pattern.value(phase: phase) / 100 primary = nil weekly = nil credits = nil stale = false } else { // Keep loading animation layout stable: IconRenderer switches layouts at `weeklyRemaining == 0`. primary = max(pattern.value(phase: phase), Self.loadingPercentEpsilon) weekly = max( pattern.value(phase: phase + pattern.secondaryOffset), Self.loadingPercentEpsilon) credits = nil stale = false } } let isLoading = phase != nil && self.shouldAnimate(provider: provider)