import AppKitimport CodexBarCoreimport Observationimport QuartzCore // MARK: - Status item controller (AppKit-hosted icons, SwiftUI popovers) @MainActorprotocol StatusItemControlling: AnyObject { func openMenuFromShortcut() func runLoginFlowFromSettings(provider: UsageProvider) async func celebrationOriginPoint(for provider: UsageProvider?) -> CGPoint? func trimRebuildableCachesForMemoryPressure() -> MemoryPressureCacheTrimSummary #if DEBUG func seedRebuildableCachesForMemoryPressureProof() #endif func prepareForAppShutdown()} extension StatusItemControlling { func celebrationOriginPoint(for provider: UsageProvider?) -> CGPoint? { nil } func trimRebuildableCachesForMemoryPressure() -> MemoryPressureCacheTrimSummary { MemoryPressureCacheTrimSummary() } #if DEBUG func seedRebuildableCachesForMemoryPressureProof() {} #endif func prepareForAppShutdown() {}} struct NativeHighlightDeferredMenuRebuild { let provider: UsageProvider?} @MainActorfinal class StatusItemController: NSObject, NSMenuDelegate, StatusItemControlling { // Disable SwiftUI menu cards + menu refresh work in tests to avoid swiftpm-testing-helper crashes. static var menuCardRenderingEnabled = !SettingsStore.isRunningTests private static let defaultMenuRefreshEnabled = !SettingsStore.isRunningTests private(set) static var menuRefreshEnabled = !SettingsStore.isRunningTests static let quotaWarningFlashDuration: TimeInterval = 60 private nonisolated static let statusItemAccessibilityTitle = "CodexBar" private nonisolated static let debugStatusItemAccessibilityTitle = "CodexBar Debug" private nonisolated static let statusItemAccessibilityIdentifierPrefix = "CodexBar.StatusItem" private nonisolated static let mergedLegacyDefaultItemIndex = 0 enum StatusItemIdentity { case merged case provider(UsageProvider) var autosaveName: String { switch self { case .merged: "codexbar-merged" case let .provider(provider): "codexbar-\(provider.rawValue)" } } var accessibilityIdentifier: String { switch self { case .merged: StatusItemController.statusItemAccessibilityIdentifierPrefix case let .provider(provider): "\(StatusItemController.statusItemAccessibilityIdentifierPrefix).\(provider.rawValue)" } } } nonisolated static func isDebugApp(bundleIdentifier: String?) -> Bool { bundleIdentifier?.contains(".debug") == true } nonisolated static func statusItemAccessibilityTitle(isDebugApp: Bool) -> String { isDebugApp ? self.debugStatusItemAccessibilityTitle : self.statusItemAccessibilityTitle } #if DEBUG var menuRefreshEnabledOverrideForTesting: Bool? #endif typealias Factory = @MainActor ( UsageStore, SettingsStore, AccountInfo, UpdaterProviding, PreferencesSelection, ManagedCodexAccountCoordinator, CodexAccountPromotionCoordinator) -> StatusItemControlling // swiftlint:disable:next function_parameter_count static func makeDefaultController( store: UsageStore, settings: SettingsStore, account: AccountInfo, updater: UpdaterProviding, selection: PreferencesSelection, managedCodexAccountCoordinator: ManagedCodexAccountCoordinator, codexAccountPromotionCoordinator: CodexAccountPromotionCoordinator) -> StatusItemControlling { StatusItemController( store: store, settings: settings, account: account, updater: updater, preferencesSelection: selection, managedCodexAccountCoordinator: managedCodexAccountCoordinator, codexAccountPromotionCoordinator: codexAccountPromotionCoordinator) } static let defaultFactory: Factory = StatusItemController.makeDefaultController static var factory: Factory = StatusItemController.defaultFactory let store: UsageStore let settings: SettingsStore let agentSessions: AgentSessionsStore lazy var menuCardRefreshMonitor = self.makeMenuCardRefreshMonitor() let account: AccountInfo let updater: UpdaterProviding let managedCodexAccountCoordinator: ManagedCodexAccountCoordinator let codexAccountPromotionCoordinator: CodexAccountPromotionCoordinator let statusBar: NSStatusBar let menuCardRenderingEnabledForController: Bool let menuRefreshEnabledForController: Bool var statusItem: NSStatusItem var statusItems: [UsageProvider: NSStatusItem] = [:] /// App intent survives Tahoe changing `NSStatusItem.isVisible` after Control Center rejects its scene. var expectedVisibleStatusItemAutosaveNames: Set<String> = [] var lastMenuProvider: UsageProvider? var menuProviders: [ObjectIdentifier: UsageProvider] = [:] var menuSession = MenuSessionCoordinator<ObjectIdentifier>() var menuReadinessSignatures: [ObjectIdentifier: String] = [:] let hostedSubviewRenderSignatures = NSMapTable<NSMenu, HostedSubviewRenderSignatureBox>.weakToStrongObjects() /// Persistent Refresh rows are weakly tracked so their enabled state can change during menu tracking. let persistentRefreshItems = NSHashTable<NSMenuItem>.weakObjects() var menuCardHeightCache: [MenuCardHeightCacheKey: CGFloat] = [:] var measuredStandardMenuWidthCache: [String: CGFloat] = [:] var lastMenuAdjunctReadinessSignature = "" var lastMenuAdjunctReadinessBaselineVersion = 0 var rootOpenHandledMenuObservationSignature: String? var mergedMenu: NSMenu? var providerMenus: [UsageProvider: NSMenu] = [:] var fallbackMenu: NSMenu? var openMenus: [ObjectIdentifier: NSMenu] = [:] var menuRefreshTasks: [ObjectIdentifier: Task<Void, Never>] = [:] /// Manual refreshes tracked per scope so refreshing one provider neither greys out nor blocks /// a manual refresh of another. `.global` covers the all-providers refresh (⌘R / merged overview). var manualRefreshTasks: [ManualRefreshScope: Task<Void, Never>] = [:] var closedMenuRebuildTasks: [ObjectIdentifier: Task<Void, Never>] = [:] var closedMenuRebuildRequests = MenuRebuildRequestRegistry<ObjectIdentifier>() var openMenuRebuildTasks: [ObjectIdentifier: Task<Void, Never>] = [:] var openMenuRebuildRequests = MenuRebuildRequestRegistry<ObjectIdentifier>() var menuIdentitySignatures: [ObjectIdentifier: String] = [:] var codexAccountMenuProjectionRevalidationTask: Task<Void, Never>? var openMenuRebuildsClosingHostedSubviewMenus: Set<ObjectIdentifier> = [] var parentMenuRebuildPendingAfterHostedSubviewClose = false var deferredMenuInteractionRefreshProviders: Set<UsageProvider> = [] var deferredMenuInteractionRefreshPending: Bool { !self.deferredMenuInteractionRefreshProviders.isEmpty } var deferredOpenAIDashboardRefreshReason: String? var deferredMenuInteractionRefreshTask: Task<Void, Never>? var highlightedMenuItems: [ObjectIdentifier: NSMenuItem] = [:] /// Open-menu rebuilds paused so AppKit's native selection background cannot retain stale geometry. var nativeHighlightDeferredMenuRebuilds: [ObjectIdentifier: NativeHighlightDeferredMenuRebuild] = [:] /// Baseline resync intent survives rebuild coalescing and any native-row or hosted-submenu deferral. var pendingMenuBaselineResyncs: Set<ObjectIdentifier> = [] var providerSwitcherShortcutEventMonitor: ProviderSwitcherShortcutEventMonitor? var providerSwitcherShortcutMenuID: ObjectIdentifier? var providerSwitcherPointerInteractionMenuID: ObjectIdentifier? var pendingProviderSwitcherPointerRebuild: PendingProviderSwitcherRebuild? var overviewScrollAccumulatedDelta: CGFloat = 0 var overviewScrollNavigationHandlerForTesting: ((OverviewScrollStep) -> Void)? var hasPreparedForAppShutdown = false var scheduleQuitTermination: (@escaping @MainActor () -> Void) -> Void = { operation in DispatchQueue.main.async { Task { @MainActor in operation() } } } var terminateApplicationForQuit: @MainActor () -> Void = { NSApp.terminate(nil) } var openMenuInvalidationRetryTask: Task<Void, Never>? #if DEBUG var onDelayedMenuRefreshAttemptForTesting: (() -> Void)? var onDeferredMenuInteractionRefreshForTesting: (() -> Void)? var onOpenMenuInvalidationRetryForTesting: (() -> Void)? var isReleasedForTesting = false var lastLoggedClosedMenuRebuildVersion: Int? var _test_openMenuRefreshYieldOverride: (@MainActor () async -> Void)? var _test_openMenuRebuildObserver: (@MainActor (NSMenu) -> Void)? var _test_providerSwitcherMenuRebuildDebounceNanoseconds: UInt64? var _test_codexAmbientLoginRunnerOverride: (@MainActor (TimeInterval) async -> CodexLoginRunner.Result)? #endif var manualRefreshViewportRestoreState = ManualRefreshViewportRestoreState() var blinkTask: Task<Void, Never>? var menuBarCountdownRefreshTask: Task<Void, Never>? var loginTask: Task<Void, Never>? { didSet { self.refreshMenusForLoginStateChange() } } var creditsPurchaseWindow: OpenAICreditsPurchaseWindowController? var activeLoginProvider: UsageProvider? { didSet { if oldValue != self.activeLoginProvider { self.refreshMenusForLoginStateChange() } } } var blinkStates: [UsageProvider: BlinkState] = [:] var blinkAmounts: [UsageProvider: CGFloat] = [:] var wiggleAmounts: [UsageProvider: CGFloat] = [:] var tiltAmounts: [UsageProvider: CGFloat] = [:] var quotaWarningFlashUntil: [UsageProvider: Date] = [:] var quotaWarningFlashTasks: [UsageProvider: Task<Void, Never>] = [:] var blinkForceUntil: Date? var loginPhase: LoginPhase = .idle { didSet { if oldValue != self.loginPhase { self.refreshMenusForLoginStateChange() } } } let preferencesSelection: PreferencesSelection var animationDriver: DisplayLinkDriver? var animationPhase: Double = 0 var animationPattern: LoadingPattern = .knightRider var animationStartedAt: Date? private var lastConfigRevision: Int private var lastProviderOrder: [UsageProvider] private var lastMergeIcons: Bool private var lastSwitcherShowsIcons: Bool private var lastObservedUsageBarsShowUsed: Bool var lastWidgetDisplaySettingsSignature = "" var lastAgentSessionsEnabled: Bool var lastAgentSessionsManualHosts: String var lastAgentSessionsRefreshFrequency: RefreshFrequency var lastAdaptiveActivityScanningEnabled: Bool /// Tracks which `usageBarsShowUsed` mode the provider switcher was built with. /// Used to decide whether we can "smart update" menu content without rebuilding the switcher. var lastSwitcherUsageBarsShowUsed: Bool /// Tracks whether the merged-menu switcher was built with the Overview tab visible. /// Used to force switcher rebuilds when Overview availability toggles. var lastSwitcherIncludesOverview: Bool = false /// Tracks localization-sensitive labels used by the merged menu. /// Used to force menu rebuilds when app language changes. var lastMenuLocalizationSignature: String = "" /// Tracks which providers the merged menu's switcher was built with, to detect when it needs full rebuild. var lastSwitcherProviders: [UsageProvider] = [] /// Tracks which switcher tab state was used for the current merged-menu switcher instance. var lastMergedSwitcherSelection: ProviderSwitcherSelection? /// Tracks which provider/overview content is currently attached below the merged-menu switcher. var lastMergedMenuContentSelection: ProviderSwitcherSelection? /// Tracks the visible Codex account switcher contents for merged-menu smart updates. var lastCodexAccountMenuDisplay: CodexAccountMenuDisplay? /// Tracks the visible token account switcher contents for merged-menu smart updates. var lastTokenAccountMenuDisplay: TokenAccountMenuDisplay? /// Keeps detached merged-menu tab content reusable while the same menu remains open. var mergedSwitcherContentCaches: [ObjectIdentifier: [ProviderSwitcherSelection: CachedMergedSwitcherMenuContent]] = [:] var preservesMergedSwitcherContentCachesDuringInvalidation = false /// Card hosting views harvested from items about to be discarded by the current populate /// pass, keyed by card identifier; consumed by `makeMenuCardItem` and cleared when the /// pass finishes. Never outlives a single synchronous menu population. var menuCardViewRecyclePool: [String: NSView] = [:] /// Monotonic token used to ignore stale deferred provider-switcher menu rebuilds. var providerSwitcherUpdateToken = 0 var providerSelectionUIRefreshTask: Task<Void, Never>? var deferredMergedIconRenderAfterTracking = false var lastAppliedMergedIconRenderSignature: String? var lastAppliedProviderIconRenderSignatures: [UsageProvider: String] = [:] let menuBarLayoutRenderer = MenuBarLayoutRenderer() var lastObservedStoreIconWorkSignature: String? var iconPerfRefreshCycleMetrics: IconPerfRefreshCycleMetrics? var iconPerfUpdatePassActive = false var lastKnownScreenCount: Int var pendingScreenChangePreviousCount: Int? var screenChangeVisibilityTask: Task<Void, Never>? let loginLogger = CodexBarLog.logger(LogCategories.login) let menuLogger = CodexBarLog.logger(LogCategories.app) var selectedMenuProvider: UsageProvider? { get { self.settings.selectedMenuProvider } set { self.settings.selectedMenuProvider = newValue } } static func makeStatusItem( statusBar: NSStatusBar, identity: StatusItemIdentity, defaults: UserDefaults, legacyDefaultItemIndex: Int?, onCreated: ((NSStatusItem) -> Void)? = nil) -> NSStatusItem { MenuBarStatusItemPlacementPreflight.prepare( defaults: defaults, autosaveName: identity.autosaveName, legacyDefaultItemIndex: legacyDefaultItemIndex) let item = statusBar.statusItem(withLength: NSStatusItem.variableLength) onCreated?(item) item.autosaveName = identity.autosaveName if let button = item.button { let title = self.statusItemAccessibilityTitle( isDebugApp: self.isDebugApp(bundleIdentifier: Bundle.main.bundleIdentifier)) // Ensure the icon is rendered at 1:1 without resampling (crisper edges for template images). button.imageScaling = .scaleNone button.setAccessibilityIdentifier(identity.accessibilityIdentifier) button.setAccessibilityTitle(title) } return item } struct BlinkState { var nextBlink: Date var blinkStart: Date? var pendingSecondStart: Date? var effect: MotionEffect = .blink static func randomDelay() -> TimeInterval { Double.random(in: 3...12) } } enum MotionEffect { case blink case wiggle case tilt } enum LoginPhase { case idle case requesting case waitingBrowser } func menuBarMetricWindow(for provider: UsageProvider, snapshot: UsageSnapshot?, now: Date = Date()) -> RateWindow? { if provider == .codex { return self.codexMenuBarMetricWindow(snapshot: snapshot, now: now) } return MenuBarMetricWindowResolver.rateWindow( preference: self.settings.menuBarMetricPreference(for: provider, snapshot: snapshot), provider: provider, snapshot: snapshot, supportsAverage: self.settings.menuBarMetricSupportsAverage(for: provider), antigravityPrioritizeExhaustedQuotas: self.settings.antigravityPrioritizeExhaustedQuotas, now: now) } private func codexMenuBarMetricWindow(snapshot: UsageSnapshot?, now: Date) -> RateWindow? { guard let snapshot else { return nil } return self.store.codexMenuBarMetricWindow(snapshot: snapshot, now: now) } init( store: UsageStore, settings: SettingsStore, account: AccountInfo, updater: UpdaterProviding, preferencesSelection: PreferencesSelection, managedCodexAccountCoordinator: ManagedCodexAccountCoordinator = ManagedCodexAccountCoordinator(), codexAccountPromotionCoordinator: CodexAccountPromotionCoordinator? = nil, statusBar: NSStatusBar = .system, menuCardRenderingEnabled: Bool = StatusItemController.menuCardRenderingEnabled, menuRefreshEnabled: Bool = StatusItemController.menuRefreshEnabled, observeProviderConfigNotifications: Bool = !SettingsStore.isRunningTests) { if SettingsStore.isRunningTests { _ = NSApplication.shared } self.store = store self.settings = settings self.agentSessions = AgentSessionsStore(settings: settings) self.account = account self.updater = updater self.preferencesSelection = preferencesSelection self.managedCodexAccountCoordinator = managedCodexAccountCoordinator self.codexAccountPromotionCoordinator = codexAccountPromotionCoordinator ?? CodexAccountPromotionCoordinator( settingsStore: settings, usageStore: store, managedAccountCoordinator: managedCodexAccountCoordinator) self.lastConfigRevision = settings.configRevision self.lastProviderOrder = settings.providerOrder self.lastMergeIcons = settings.mergeIcons self.lastSwitcherShowsIcons = settings.switcherShowsIcons self.lastObservedUsageBarsShowUsed = settings.usageBarsShowUsed self.lastAgentSessionsEnabled = settings.agentSessionsEnabled self.lastAgentSessionsManualHosts = settings.agentSessionsManualHosts self.lastAgentSessionsRefreshFrequency = settings.refreshFrequency self.lastAdaptiveActivityScanningEnabled = settings.adaptiveActivityScanningEnabled self.lastSwitcherUsageBarsShowUsed = settings.usageBarsShowUsed self.menuCardRenderingEnabledForController = menuCardRenderingEnabled self.menuRefreshEnabledForController = menuRefreshEnabled let repairedStatusItemVisibilityKeys = MenuBarStatusItemDefaultsRepair .repairHiddenVisibilityDefaultsIfNeeded(defaults: settings.userDefaults) self.statusBar = statusBar self.statusItem = Self.makeStatusItem( statusBar: statusBar, identity: .merged, defaults: settings.userDefaults, legacyDefaultItemIndex: Self.mergedLegacyDefaultItemIndex) self.lastKnownScreenCount = NSScreen.screens.count // Status items for individual providers are now created lazily in updateVisibility() super.init() if !repairedStatusItemVisibilityKeys.isEmpty { self.menuLogger.info( "Repaired hidden macOS status-item visibility defaults", metadata: ["keys": repairedStatusItemVisibilityKeys.joined(separator: ",")]) } self.lastMenuAdjunctReadinessSignature = self.menuAdjunctReadinessSignature() self.lastMenuAdjunctReadinessBaselineVersion = self.menuSession.contentVersion self.lastWidgetDisplaySettingsSignature = self.widgetDisplaySettingsSignature() self.wireBindings() self.wireAgentSessionUpdates() if !SettingsStore.isRunningTests { self.agentSessions.start() } self.updateVisibility() self.updateIcons() self.scheduleCodexAccountMenuProjectionRevalidationIfNeeded( for: self.store.enabledProvidersForDisplay()) self.scheduleStartupStatusItemVisibilityCheck() NotificationCenter.default.addObserver( self, selector: #selector(self.handleDebugReplayNotification(_:)), name: .codexbarDebugReplayAllAnimations, object: nil) NotificationCenter.default.addObserver( self, selector: #selector(self.handleDebugBlinkNotification), name: .codexbarDebugBlinkNow, object: nil) NotificationCenter.default.addObserver( self, selector: #selector(self.handleQuotaWarningPosted(_:)), name: .codexbarQuotaWarningDidPost, object: nil) if observeProviderConfigNotifications { NotificationCenter.default.addObserver( self, selector: #selector(self.handleProviderConfigDidChange), name: .codexbarProviderConfigDidChange, object: nil) } NotificationCenter.default.addObserver( self, selector: #selector(self.handleScreenParametersDidChange(_:)), name: NSApplication.didChangeScreenParametersNotification, object: nil) self.observeMenuBarTimeEnvironmentChanges() } convenience init( store: UsageStore, settings: SettingsStore, account: AccountInfo, updater: UpdaterProviding, preferencesSelection: PreferencesSelection, statusBar: NSStatusBar = .system, menuCardRenderingEnabled: Bool = StatusItemController.menuCardRenderingEnabled, menuRefreshEnabled: Bool = StatusItemController.menuRefreshEnabled, observeProviderConfigNotifications: Bool = !SettingsStore.isRunningTests) { self.init( store: store, settings: settings, account: account, updater: updater, preferencesSelection: preferencesSelection, managedCodexAccountCoordinator: ManagedCodexAccountCoordinator(), codexAccountPromotionCoordinator: nil, statusBar: statusBar, menuCardRenderingEnabled: menuCardRenderingEnabled, menuRefreshEnabled: menuRefreshEnabled, observeProviderConfigNotifications: observeProviderConfigNotifications) } private func wireBindings() { self.observeStoreChanges() self.observeStoreIconChanges()Lines 1–500 of 1016. Load more
import AppKit import CodexBarCore import Observation import QuartzCore // MARK: - Status item controller (AppKit-hosted icons, SwiftUI popovers) @MainActor protocol StatusItemControlling: AnyObject { func openMenuFromShortcut() func runLoginFlowFromSettings(provider: UsageProvider) async func celebrationOriginPoint(for provider: UsageProvider?) -> CGPoint? func trimRebuildableCachesForMemoryPressure() -> MemoryPressureCacheTrimSummary #if DEBUG func seedRebuildableCachesForMemoryPressureProof() #endif func prepareForAppShutdown() } extension StatusItemControlling { func celebrationOriginPoint(for provider: UsageProvider?) -> CGPoint? { nil } func trimRebuildableCachesForMemoryPressure() -> MemoryPressureCacheTrimSummary { MemoryPressureCacheTrimSummary() } #if DEBUG func seedRebuildableCachesForMemoryPressureProof() {} #endif func prepareForAppShutdown() {} } struct NativeHighlightDeferredMenuRebuild { let provider: UsageProvider? } @MainActor final class StatusItemController: NSObject, NSMenuDelegate, StatusItemControlling { // Disable SwiftUI menu cards + menu refresh work in tests to avoid swiftpm-testing-helper crashes. static var menuCardRenderingEnabled = !SettingsStore.isRunningTests private static let defaultMenuRefreshEnabled = !SettingsStore.isRunningTests private(set) static var menuRefreshEnabled = !SettingsStore.isRunningTests static let quotaWarningFlashDuration: TimeInterval = 60 private nonisolated static let statusItemAccessibilityTitle = "CodexBar" private nonisolated static let debugStatusItemAccessibilityTitle = "CodexBar Debug" private nonisolated static let statusItemAccessibilityIdentifierPrefix = "CodexBar.StatusItem" private nonisolated static let mergedLegacyDefaultItemIndex = 0 enum StatusItemIdentity { case merged case provider(UsageProvider) var autosaveName: String { switch self { case .merged: "codexbar-merged" case let .provider(provider): "codexbar-\(provider.rawValue)" } } var accessibilityIdentifier: String { switch self { case .merged: StatusItemController.statusItemAccessibilityIdentifierPrefix case let .provider(provider): "\(StatusItemController.statusItemAccessibilityIdentifierPrefix).\(provider.rawValue)" } } } nonisolated static func isDebugApp(bundleIdentifier: String?) -> Bool { bundleIdentifier?.contains(".debug") == true } nonisolated static func statusItemAccessibilityTitle(isDebugApp: Bool) -> String { isDebugApp ? self.debugStatusItemAccessibilityTitle : self.statusItemAccessibilityTitle } #if DEBUG var menuRefreshEnabledOverrideForTesting: Bool? #endif typealias Factory = @MainActor ( UsageStore, SettingsStore, AccountInfo, UpdaterProviding, PreferencesSelection, ManagedCodexAccountCoordinator, CodexAccountPromotionCoordinator) -> StatusItemControlling // swiftlint:disable:next function_parameter_count static func makeDefaultController( store: UsageStore, settings: SettingsStore, account: AccountInfo, updater: UpdaterProviding, selection: PreferencesSelection, managedCodexAccountCoordinator: ManagedCodexAccountCoordinator, codexAccountPromotionCoordinator: CodexAccountPromotionCoordinator) -> StatusItemControlling { StatusItemController( store: store, settings: settings, account: account, updater: updater, preferencesSelection: selection, managedCodexAccountCoordinator: managedCodexAccountCoordinator, codexAccountPromotionCoordinator: codexAccountPromotionCoordinator) } static let defaultFactory: Factory = StatusItemController.makeDefaultController static var factory: Factory = StatusItemController.defaultFactory let store: UsageStore let settings: SettingsStore let agentSessions: AgentSessionsStore lazy var menuCardRefreshMonitor = self.makeMenuCardRefreshMonitor() let account: AccountInfo let updater: UpdaterProviding let managedCodexAccountCoordinator: ManagedCodexAccountCoordinator let codexAccountPromotionCoordinator: CodexAccountPromotionCoordinator let statusBar: NSStatusBar let menuCardRenderingEnabledForController: Bool let menuRefreshEnabledForController: Bool var statusItem: NSStatusItem var statusItems: [UsageProvider: NSStatusItem] = [:] /// App intent survives Tahoe changing `NSStatusItem.isVisible` after Control Center rejects its scene. var expectedVisibleStatusItemAutosaveNames: Set<String> = [] var lastMenuProvider: UsageProvider? var menuProviders: [ObjectIdentifier: UsageProvider] = [:] var menuSession = MenuSessionCoordinator<ObjectIdentifier>() var menuReadinessSignatures: [ObjectIdentifier: String] = [:] let hostedSubviewRenderSignatures = NSMapTable<NSMenu, HostedSubviewRenderSignatureBox>.weakToStrongObjects() /// Persistent Refresh rows are weakly tracked so their enabled state can change during menu tracking. let persistentRefreshItems = NSHashTable<NSMenuItem>.weakObjects() var menuCardHeightCache: [MenuCardHeightCacheKey: CGFloat] = [:] var measuredStandardMenuWidthCache: [String: CGFloat] = [:] var lastMenuAdjunctReadinessSignature = "" var lastMenuAdjunctReadinessBaselineVersion = 0 var rootOpenHandledMenuObservationSignature: String? var mergedMenu: NSMenu? var providerMenus: [UsageProvider: NSMenu] = [:] var fallbackMenu: NSMenu? var openMenus: [ObjectIdentifier: NSMenu] = [:] var menuRefreshTasks: [ObjectIdentifier: Task<Void, Never>] = [:] /// Manual refreshes tracked per scope so refreshing one provider neither greys out nor blocks /// a manual refresh of another. `.global` covers the all-providers refresh (⌘R / merged overview). var manualRefreshTasks: [ManualRefreshScope: Task<Void, Never>] = [:] var closedMenuRebuildTasks: [ObjectIdentifier: Task<Void, Never>] = [:] var closedMenuRebuildRequests = MenuRebuildRequestRegistry<ObjectIdentifier>() var openMenuRebuildTasks: [ObjectIdentifier: Task<Void, Never>] = [:] var openMenuRebuildRequests = MenuRebuildRequestRegistry<ObjectIdentifier>() var menuIdentitySignatures: [ObjectIdentifier: String] = [:] var codexAccountMenuProjectionRevalidationTask: Task<Void, Never>? var openMenuRebuildsClosingHostedSubviewMenus: Set<ObjectIdentifier> = [] var parentMenuRebuildPendingAfterHostedSubviewClose = false var deferredMenuInteractionRefreshProviders: Set<UsageProvider> = [] var deferredMenuInteractionRefreshPending: Bool { !self.deferredMenuInteractionRefreshProviders.isEmpty } var deferredOpenAIDashboardRefreshReason: String? var deferredMenuInteractionRefreshTask: Task<Void, Never>? var highlightedMenuItems: [ObjectIdentifier: NSMenuItem] = [:] /// Open-menu rebuilds paused so AppKit's native selection background cannot retain stale geometry. var nativeHighlightDeferredMenuRebuilds: [ObjectIdentifier: NativeHighlightDeferredMenuRebuild] = [:] /// Baseline resync intent survives rebuild coalescing and any native-row or hosted-submenu deferral. var pendingMenuBaselineResyncs: Set<ObjectIdentifier> = [] var providerSwitcherShortcutEventMonitor: ProviderSwitcherShortcutEventMonitor? var providerSwitcherShortcutMenuID: ObjectIdentifier? var providerSwitcherPointerInteractionMenuID: ObjectIdentifier? var pendingProviderSwitcherPointerRebuild: PendingProviderSwitcherRebuild? var overviewScrollAccumulatedDelta: CGFloat = 0 var overviewScrollNavigationHandlerForTesting: ((OverviewScrollStep) -> Void)? var hasPreparedForAppShutdown = false var scheduleQuitTermination: (@escaping @MainActor () -> Void) -> Void = { operation in DispatchQueue.main.async { Task { @MainActor in operation() } } } var terminateApplicationForQuit: @MainActor () -> Void = { NSApp.terminate(nil) } var openMenuInvalidationRetryTask: Task<Void, Never>? #if DEBUG var onDelayedMenuRefreshAttemptForTesting: (() -> Void)? var onDeferredMenuInteractionRefreshForTesting: (() -> Void)? var onOpenMenuInvalidationRetryForTesting: (() -> Void)? var isReleasedForTesting = false var lastLoggedClosedMenuRebuildVersion: Int? var _test_openMenuRefreshYieldOverride: (@MainActor () async -> Void)? var _test_openMenuRebuildObserver: (@MainActor (NSMenu) -> Void)? var _test_providerSwitcherMenuRebuildDebounceNanoseconds: UInt64? var _test_codexAmbientLoginRunnerOverride: (@MainActor (TimeInterval) async -> CodexLoginRunner.Result)? #endif var manualRefreshViewportRestoreState = ManualRefreshViewportRestoreState() var blinkTask: Task<Void, Never>? var menuBarCountdownRefreshTask: Task<Void, Never>? var loginTask: Task<Void, Never>? { didSet { self.refreshMenusForLoginStateChange() } } var creditsPurchaseWindow: OpenAICreditsPurchaseWindowController? var activeLoginProvider: UsageProvider? { didSet { if oldValue != self.activeLoginProvider { self.refreshMenusForLoginStateChange() } } } var blinkStates: [UsageProvider: BlinkState] = [:] var blinkAmounts: [UsageProvider: CGFloat] = [:] var wiggleAmounts: [UsageProvider: CGFloat] = [:] var tiltAmounts: [UsageProvider: CGFloat] = [:] var quotaWarningFlashUntil: [UsageProvider: Date] = [:] var quotaWarningFlashTasks: [UsageProvider: Task<Void, Never>] = [:] var blinkForceUntil: Date? var loginPhase: LoginPhase = .idle { didSet { if oldValue != self.loginPhase { self.refreshMenusForLoginStateChange() } } } let preferencesSelection: PreferencesSelection var animationDriver: DisplayLinkDriver? var animationPhase: Double = 0 var animationPattern: LoadingPattern = .knightRider var animationStartedAt: Date? private var lastConfigRevision: Int private var lastProviderOrder: [UsageProvider] private var lastMergeIcons: Bool private var lastSwitcherShowsIcons: Bool private var lastObservedUsageBarsShowUsed: Bool var lastWidgetDisplaySettingsSignature = "" var lastAgentSessionsEnabled: Bool var lastAgentSessionsManualHosts: String var lastAgentSessionsRefreshFrequency: RefreshFrequency var lastAdaptiveActivityScanningEnabled: Bool /// Tracks which `usageBarsShowUsed` mode the provider switcher was built with. /// Used to decide whether we can "smart update" menu content without rebuilding the switcher. var lastSwitcherUsageBarsShowUsed: Bool /// Tracks whether the merged-menu switcher was built with the Overview tab visible. /// Used to force switcher rebuilds when Overview availability toggles. var lastSwitcherIncludesOverview: Bool = false /// Tracks localization-sensitive labels used by the merged menu. /// Used to force menu rebuilds when app language changes. var lastMenuLocalizationSignature: String = "" /// Tracks which providers the merged menu's switcher was built with, to detect when it needs full rebuild. var lastSwitcherProviders: [UsageProvider] = [] /// Tracks which switcher tab state was used for the current merged-menu switcher instance. var lastMergedSwitcherSelection: ProviderSwitcherSelection? /// Tracks which provider/overview content is currently attached below the merged-menu switcher. var lastMergedMenuContentSelection: ProviderSwitcherSelection? /// Tracks the visible Codex account switcher contents for merged-menu smart updates. var lastCodexAccountMenuDisplay: CodexAccountMenuDisplay? /// Tracks the visible token account switcher contents for merged-menu smart updates. var lastTokenAccountMenuDisplay: TokenAccountMenuDisplay? /// Keeps detached merged-menu tab content reusable while the same menu remains open. var mergedSwitcherContentCaches: [ObjectIdentifier: [ProviderSwitcherSelection: CachedMergedSwitcherMenuContent]] = [:] var preservesMergedSwitcherContentCachesDuringInvalidation = false /// Card hosting views harvested from items about to be discarded by the current populate /// pass, keyed by card identifier; consumed by `makeMenuCardItem` and cleared when the /// pass finishes. Never outlives a single synchronous menu population. var menuCardViewRecyclePool: [String: NSView] = [:] /// Monotonic token used to ignore stale deferred provider-switcher menu rebuilds. var providerSwitcherUpdateToken = 0 var providerSelectionUIRefreshTask: Task<Void, Never>? var deferredMergedIconRenderAfterTracking = false var lastAppliedMergedIconRenderSignature: String? var lastAppliedProviderIconRenderSignatures: [UsageProvider: String] = [:] let menuBarLayoutRenderer = MenuBarLayoutRenderer() var lastObservedStoreIconWorkSignature: String? var iconPerfRefreshCycleMetrics: IconPerfRefreshCycleMetrics? var iconPerfUpdatePassActive = false var lastKnownScreenCount: Int var pendingScreenChangePreviousCount: Int? var screenChangeVisibilityTask: Task<Void, Never>? let loginLogger = CodexBarLog.logger(LogCategories.login) let menuLogger = CodexBarLog.logger(LogCategories.app) var selectedMenuProvider: UsageProvider? { get { self.settings.selectedMenuProvider } set { self.settings.selectedMenuProvider = newValue } } static func makeStatusItem( statusBar: NSStatusBar, identity: StatusItemIdentity, defaults: UserDefaults, legacyDefaultItemIndex: Int?, onCreated: ((NSStatusItem) -> Void)? = nil) -> NSStatusItem { MenuBarStatusItemPlacementPreflight.prepare( defaults: defaults, autosaveName: identity.autosaveName, legacyDefaultItemIndex: legacyDefaultItemIndex) let item = statusBar.statusItem(withLength: NSStatusItem.variableLength) onCreated?(item) item.autosaveName = identity.autosaveName if let button = item.button { let title = self.statusItemAccessibilityTitle( isDebugApp: self.isDebugApp(bundleIdentifier: Bundle.main.bundleIdentifier)) // Ensure the icon is rendered at 1:1 without resampling (crisper edges for template images). button.imageScaling = .scaleNone button.setAccessibilityIdentifier(identity.accessibilityIdentifier) button.setAccessibilityTitle(title) } return item } struct BlinkState { var nextBlink: Date var blinkStart: Date? var pendingSecondStart: Date? var effect: MotionEffect = .blink static func randomDelay() -> TimeInterval { Double.random(in: 3...12) } } enum MotionEffect { case blink case wiggle case tilt } enum LoginPhase { case idle case requesting case waitingBrowser } func menuBarMetricWindow(for provider: UsageProvider, snapshot: UsageSnapshot?, now: Date = Date()) -> RateWindow? { if provider == .codex { return self.codexMenuBarMetricWindow(snapshot: snapshot, now: now) } return MenuBarMetricWindowResolver.rateWindow( preference: self.settings.menuBarMetricPreference(for: provider, snapshot: snapshot), provider: provider, snapshot: snapshot, supportsAverage: self.settings.menuBarMetricSupportsAverage(for: provider), antigravityPrioritizeExhaustedQuotas: self.settings.antigravityPrioritizeExhaustedQuotas, now: now) } private func codexMenuBarMetricWindow(snapshot: UsageSnapshot?, now: Date) -> RateWindow? { guard let snapshot else { return nil } return self.store.codexMenuBarMetricWindow(snapshot: snapshot, now: now) } init( store: UsageStore, settings: SettingsStore, account: AccountInfo, updater: UpdaterProviding, preferencesSelection: PreferencesSelection, managedCodexAccountCoordinator: ManagedCodexAccountCoordinator = ManagedCodexAccountCoordinator(), codexAccountPromotionCoordinator: CodexAccountPromotionCoordinator? = nil, statusBar: NSStatusBar = .system, menuCardRenderingEnabled: Bool = StatusItemController.menuCardRenderingEnabled, menuRefreshEnabled: Bool = StatusItemController.menuRefreshEnabled, observeProviderConfigNotifications: Bool = !SettingsStore.isRunningTests) { if SettingsStore.isRunningTests { _ = NSApplication.shared } self.store = store self.settings = settings self.agentSessions = AgentSessionsStore(settings: settings) self.account = account self.updater = updater self.preferencesSelection = preferencesSelection self.managedCodexAccountCoordinator = managedCodexAccountCoordinator self.codexAccountPromotionCoordinator = codexAccountPromotionCoordinator ?? CodexAccountPromotionCoordinator( settingsStore: settings, usageStore: store, managedAccountCoordinator: managedCodexAccountCoordinator) self.lastConfigRevision = settings.configRevision self.lastProviderOrder = settings.providerOrder self.lastMergeIcons = settings.mergeIcons self.lastSwitcherShowsIcons = settings.switcherShowsIcons self.lastObservedUsageBarsShowUsed = settings.usageBarsShowUsed self.lastAgentSessionsEnabled = settings.agentSessionsEnabled self.lastAgentSessionsManualHosts = settings.agentSessionsManualHosts self.lastAgentSessionsRefreshFrequency = settings.refreshFrequency self.lastAdaptiveActivityScanningEnabled = settings.adaptiveActivityScanningEnabled self.lastSwitcherUsageBarsShowUsed = settings.usageBarsShowUsed self.menuCardRenderingEnabledForController = menuCardRenderingEnabled self.menuRefreshEnabledForController = menuRefreshEnabled let repairedStatusItemVisibilityKeys = MenuBarStatusItemDefaultsRepair .repairHiddenVisibilityDefaultsIfNeeded(defaults: settings.userDefaults) self.statusBar = statusBar self.statusItem = Self.makeStatusItem( statusBar: statusBar, identity: .merged, defaults: settings.userDefaults, legacyDefaultItemIndex: Self.mergedLegacyDefaultItemIndex) self.lastKnownScreenCount = NSScreen.screens.count // Status items for individual providers are now created lazily in updateVisibility() super.init() if !repairedStatusItemVisibilityKeys.isEmpty { self.menuLogger.info( "Repaired hidden macOS status-item visibility defaults", metadata: ["keys": repairedStatusItemVisibilityKeys.joined(separator: ",")]) } self.lastMenuAdjunctReadinessSignature = self.menuAdjunctReadinessSignature() self.lastMenuAdjunctReadinessBaselineVersion = self.menuSession.contentVersion self.lastWidgetDisplaySettingsSignature = self.widgetDisplaySettingsSignature() self.wireBindings() self.wireAgentSessionUpdates() if !SettingsStore.isRunningTests { self.agentSessions.start() } self.updateVisibility() self.updateIcons() self.scheduleCodexAccountMenuProjectionRevalidationIfNeeded( for: self.store.enabledProvidersForDisplay()) self.scheduleStartupStatusItemVisibilityCheck() NotificationCenter.default.addObserver( self, selector: #selector(self.handleDebugReplayNotification(_:)), name: .codexbarDebugReplayAllAnimations, object: nil) NotificationCenter.default.addObserver( self, selector: #selector(self.handleDebugBlinkNotification), name: .codexbarDebugBlinkNow, object: nil) NotificationCenter.default.addObserver( self, selector: #selector(self.handleQuotaWarningPosted(_:)), name: .codexbarQuotaWarningDidPost, object: nil) if observeProviderConfigNotifications { NotificationCenter.default.addObserver( self, selector: #selector(self.handleProviderConfigDidChange), name: .codexbarProviderConfigDidChange, object: nil) } NotificationCenter.default.addObserver( self, selector: #selector(self.handleScreenParametersDidChange(_:)), name: NSApplication.didChangeScreenParametersNotification, object: nil) self.observeMenuBarTimeEnvironmentChanges() } convenience init( store: UsageStore, settings: SettingsStore, account: AccountInfo, updater: UpdaterProviding, preferencesSelection: PreferencesSelection, statusBar: NSStatusBar = .system, menuCardRenderingEnabled: Bool = StatusItemController.menuCardRenderingEnabled, menuRefreshEnabled: Bool = StatusItemController.menuRefreshEnabled, observeProviderConfigNotifications: Bool = !SettingsStore.isRunningTests) { self.init( store: store, settings: settings, account: account, updater: updater, preferencesSelection: preferencesSelection, managedCodexAccountCoordinator: ManagedCodexAccountCoordinator(), codexAccountPromotionCoordinator: nil, statusBar: statusBar, menuCardRenderingEnabled: menuCardRenderingEnabled, menuRefreshEnabled: menuRefreshEnabled, observeProviderConfigNotifications: observeProviderConfigNotifications) } private func wireBindings() { self.observeStoreChanges() self.observeStoreIconChanges()