103 lines
4.1 KiB
Swift
103 lines
4.1 KiB
Swift
import AppKit
|
|
import CodexBarCore
|
|
|
|
extension StatusItemController {
|
|
func refreshProviderSelectionDependentUI(
|
|
refreshOpenMenus: Bool = false,
|
|
deferRendering: Bool = false)
|
|
{
|
|
#if DEBUG
|
|
guard !self.isReleasedForTesting else { return }
|
|
#endif
|
|
self.advanceMenuInteraction(for: self.mergedMenu)
|
|
self.invalidateMenus(refreshOpenMenus: refreshOpenMenus)
|
|
if deferRendering {
|
|
self.scheduleProviderSelectionUIRefresh()
|
|
return
|
|
}
|
|
self.refreshProviderSelectionRendering()
|
|
}
|
|
|
|
private func scheduleProviderSelectionUIRefresh() {
|
|
self.providerSelectionUIRefreshTask?.cancel()
|
|
self.providerSelectionUIRefreshTask = Task { @MainActor [weak self] in
|
|
await Task.yield()
|
|
guard !Task.isCancelled, let self else { return }
|
|
self.refreshProviderSelectionRendering()
|
|
self.providerSelectionUIRefreshTask = nil
|
|
}
|
|
}
|
|
|
|
private func refreshProviderSelectionRendering() {
|
|
self.updateAnimationState()
|
|
self.updateBlinkingState()
|
|
let phase: Double? = self.needsMenuBarIconAnimation() ? self.animationPhase : nil
|
|
self.applyIcon(phase: phase)
|
|
}
|
|
|
|
func navigateProviderSwitcher(
|
|
_ direction: StatusItemMenuProviderNavigationDirection,
|
|
menu: NSMenu? = nil)
|
|
{
|
|
guard self.shouldMergeIcons else { return }
|
|
let enabledProviders = self.store.enabledProvidersForDisplay()
|
|
guard enabledProviders.count > 1 else { return }
|
|
|
|
let includesOverview = !self.settings.resolvedMergedOverviewProviders(
|
|
activeProviders: enabledProviders,
|
|
maxVisibleProviders: SettingsStore.mergedOverviewProviderLimit).isEmpty
|
|
var selections = enabledProviders.map(ProviderSwitcherSelection.provider)
|
|
if includesOverview {
|
|
selections.insert(.overview, at: 0)
|
|
}
|
|
|
|
let current: ProviderSwitcherSelection = if includesOverview,
|
|
self.settings.mergedMenuLastSelectedWasOverview
|
|
{
|
|
.overview
|
|
} else {
|
|
.provider(self.navigationResolvedProvider(enabledProviders: enabledProviders) ?? .codex)
|
|
}
|
|
guard let currentIndex = selections.firstIndex(of: current) else { return }
|
|
|
|
let delta = direction == .next ? 1 : -1
|
|
let nextIndex = (currentIndex + delta + selections.count) % selections.count
|
|
let selection = selections[nextIndex]
|
|
let menuProvider: UsageProvider = switch selection {
|
|
case .overview:
|
|
self.navigationResolvedProvider(enabledProviders: enabledProviders) ?? .codex
|
|
case let .provider(provider):
|
|
provider
|
|
}
|
|
self.preservingMergedSwitcherContentCachesDuringInvalidation {
|
|
switch selection {
|
|
case .overview:
|
|
self.settings.mergedMenuLastSelectedWasOverview = true
|
|
self.lastMenuProvider = self.navigationResolvedProvider(enabledProviders: enabledProviders) ?? .codex
|
|
case let .provider(provider):
|
|
self.settings.mergedMenuLastSelectedWasOverview = false
|
|
self.selectedMenuProvider = provider
|
|
self.lastMenuProvider = provider
|
|
}
|
|
self.lastMergedSwitcherSelection = selection
|
|
self.refreshProviderSelectionDependentUI(deferRendering: true)
|
|
}
|
|
let trackedMenu = menu ?? self.providerSwitcherShortcutMenuID.flatMap { self.openMenus[$0] }
|
|
if let trackedMenu {
|
|
self.requestProviderSwitcherMenuRebuild(
|
|
trackedMenu,
|
|
provider: menuProvider)
|
|
}
|
|
}
|
|
|
|
private func navigationResolvedProvider(enabledProviders: [UsageProvider]) -> UsageProvider? {
|
|
if enabledProviders.isEmpty {
|
|
return .codex
|
|
}
|
|
if let selected = self.selectedMenuProvider, enabledProviders.contains(selected) {
|
|
return selected
|
|
}
|
|
return enabledProviders.first(where: { self.store.isProviderAvailable($0) }) ?? enabledProviders.first
|
|
}
|
|
}
|