164 lines · 6.4 KB · Swift
RawDownload
import CodexBarCoreimport Foundation extension StatusItemController {    private nonisolated static let menuBarCountdownRefreshEpsilon: TimeInterval = 0.05     func scheduleMenuBarCountdownRefreshIfNeeded(now: Date = .init()) {        self.menuBarCountdownRefreshTask?.cancel()        self.menuBarCountdownRefreshTask = nil         var delays: [TimeInterval] = []        let providers = self.menuBarRefreshProviders()        let displayMode = self.settings.menuBarDisplayMode        let smartExhaustedActive = self.settings.menuBarShowsBrandIconWithPercent            && self.settings.menuBarShowsResetTimeWhenExhausted            && displayMode != .resetTime         var countdownResetDates: [Date] = []        var absoluteResetDates: [Date] = []        for provider in providers {            let resetDates = self.menuBarDisplayedResetDates(for: provider, now: now)            let resolution = self.settings.menuBarLayoutResolution(for: provider)            if !resolution.usesLegacyRendering,               self.settings.menuBarIconStyle == .iconAndPercent            {                let tokens = resolution.layout.lines.joined()                if tokens.contains(.resetCountdown) {                    countdownResetDates.append(contentsOf: resetDates)                }                if tokens.contains(.resetAbsolute) {                    absoluteResetDates.append(contentsOf: resetDates)                }                continue            }             guard self.settings.menuBarShowsBrandIconWithPercent,                  displayMode == .resetTime || smartExhaustedActive            else { continue }            switch self.settings.resetTimeDisplayStyle {            case .countdown:                countdownResetDates.append(contentsOf: resetDates)            case .absolute:                absoluteResetDates.append(contentsOf: resetDates)            }        }         if let delay = Self.menuBarCountdownRefreshDelay(resetDates: countdownResetDates, now: now) {            // Countdown text ticks every minute; refresh on each displayed-minute boundary (the last of            // which lands at the reset, flipping a smart-exhausted lane back to the percentage).            delays.append(delay)        }        if let delay = Self.menuBarAbsoluteRefreshDelay(resetDates: absoluteResetDates, now: now) {            // Absolute clocks don't tick each minute, but their human-friendly date label can change at            // local midnight (for example, "tomorrow" becomes a same-day time). Wake at that boundary or            // the reset itself, whichever comes first; the next icon update schedules any later boundary.            delays.append(delay)        }         if self.menuBarObservesCodexReset(providers: providers) {            let projection = self.store.codexConsumerProjection(surface: .menuBar, now: now)            if let resetAt = projection.nextMenuBarStateChangeAt {                delays.append(max(                    Self.menuBarCountdownRefreshEpsilon,                    resetAt.timeIntervalSince(now) + Self.menuBarCountdownRefreshEpsilon))            }        }        guard let delay = delays.min() else { return }         self.menuBarCountdownRefreshTask = Task { @MainActor [weak self] in            do {                try await Task.sleep(for: .seconds(delay))            } catch {                return            }            guard let self, !Task.isCancelled else { return }            self.menuBarCountdownRefreshTask = nil            self.updateIcons()        }    }     nonisolated static func menuBarCountdownRefreshDelay(        resetDates: [Date],        now: Date)        -> TimeInterval?    {        resetDates.compactMap { resetDate -> TimeInterval? in            let remaining = resetDate.timeIntervalSince(now)            guard remaining > 0 else { return nil }            let displayedMinutes = ceil(remaining / 60)            let nextBoundaryRemaining = max(0, displayedMinutes - 1) * 60            return max(                self.menuBarCountdownRefreshEpsilon,                remaining - nextBoundaryRemaining + self.menuBarCountdownRefreshEpsilon)        }.min()    }     nonisolated static func menuBarAbsoluteRefreshDelay(        resetDates: [Date],        now: Date,        calendar: Calendar = .current)        -> TimeInterval?    {        guard let nextDayStart = calendar.dateInterval(of: .day, for: now)?.end else { return nil }         return resetDates.compactMap { resetDate -> TimeInterval? in            guard resetDate > now else { return nil }            let nextTextChange = min(resetDate, nextDayStart)            return max(                self.menuBarCountdownRefreshEpsilon,                nextTextChange.timeIntervalSince(now) + self.menuBarCountdownRefreshEpsilon)        }.min()    }     private func menuBarRefreshProviders() -> [UsageProvider] {        if self.shouldMergeIcons {            return [self.primaryProviderForUnifiedIcon()]        }        return UsageProvider.allCases.filter(self.isVisible)    }     private func menuBarObservesCodexReset(providers: [UsageProvider]) -> Bool {        if providers.contains(.codex) {            return true        }        guard self.shouldMergeIcons, self.settings.menuBarShowsHighestUsage else {            return false        }        let activeProviders = self.store.enabledProvidersForDisplay()        return self.settings.resolvedMergedOverviewProviders(            activeProviders: activeProviders,            maxVisibleProviders: SettingsStore.mergedOverviewProviderLimit).contains(.codex)    }     func observeMenuBarTimeEnvironmentChanges() {        for name in [            Notification.Name.NSSystemClockDidChange,            .NSSystemTimeZoneDidChange,            .NSCalendarDayChanged,        ] {            NotificationCenter.default.addObserver(                self,                selector: #selector(self.handleMenuBarTimeEnvironmentDidChange),                name: name,                object: nil)        }    }     @objc nonisolated func handleMenuBarTimeEnvironmentDidChange() {        Task { @MainActor [weak self] in            guard let self, !self.hasPreparedForAppShutdown else { return }            self.handleMenuBarTimeEnvironmentChange()        }    }     func handleMenuBarTimeEnvironmentChange() {        self.updateIcons()    }     #if DEBUG    func _test_isMenuBarCountdownRefreshScheduled() -> Bool {        self.menuBarCountdownRefreshTask != nil    }    #endif}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t