chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,148 @@
|
||||
import AppKit
|
||||
import CodexBarCore
|
||||
|
||||
extension StatusItemController {
|
||||
private static let measuredStandardMenuWidthCacheLimit = 96
|
||||
|
||||
func menuCardWidth(
|
||||
for providers: [UsageProvider],
|
||||
selectedProvider: UsageProvider?,
|
||||
descriptor: MenuDescriptor) -> CGFloat
|
||||
{
|
||||
let sectionSets: [[MenuDescriptor.Section]] = if self.shouldMergeIcons, providers.count > 1 {
|
||||
providers.map { provider in
|
||||
if provider == selectedProvider {
|
||||
return descriptor.sections
|
||||
}
|
||||
return self.makeMenuDescriptor(
|
||||
provider: provider,
|
||||
includeContextualActions: true).sections
|
||||
}
|
||||
} else {
|
||||
[descriptor.sections]
|
||||
}
|
||||
return self.measuredMenuCardWidth(for: sectionSets)
|
||||
}
|
||||
|
||||
func measuredMenuCardWidth(for sectionSets: [[MenuDescriptor.Section]]) -> CGFloat {
|
||||
let baselineWidth = Self.menuCardBaseWidth
|
||||
return sectionSets.reduce(baselineWidth) { width, sections in
|
||||
max(width, self.measuredStandardMenuWidth(for: sections, baseWidth: baselineWidth))
|
||||
}
|
||||
}
|
||||
|
||||
func makeMenuDescriptor(
|
||||
provider: UsageProvider?,
|
||||
includeContextualActions: Bool) -> MenuDescriptor
|
||||
{
|
||||
MenuDescriptor.build(
|
||||
provider: provider,
|
||||
store: self.store,
|
||||
settings: self.settings,
|
||||
account: self.account,
|
||||
managedCodexAccountCoordinator: self.managedCodexAccountCoordinator,
|
||||
codexAccountPromotionCoordinator: self.codexAccountPromotionCoordinator,
|
||||
updateReady: self.updater.updateStatus.isUpdateReady,
|
||||
includeContextualActions: includeContextualActions,
|
||||
agentSessionsEnabled: self.settings.agentSessionsEnabled,
|
||||
localAgentSessions: self.agentSessions.localSessions,
|
||||
remoteAgentHosts: self.agentSessions.remoteHosts)
|
||||
}
|
||||
|
||||
func measuredStandardMenuWidth(for sections: [MenuDescriptor.Section], baseWidth: CGFloat) -> CGFloat {
|
||||
let cacheKey = self.measuredStandardMenuWidthCacheKey(for: sections, baseWidth: baseWidth)
|
||||
if let cached = self.measuredStandardMenuWidthCache[cacheKey] {
|
||||
return cached
|
||||
}
|
||||
|
||||
let measuringMenu = NSMenu()
|
||||
measuringMenu.autoenablesItems = false
|
||||
self.addActionableSections(sections, to: measuringMenu, width: baseWidth)
|
||||
let measured = ceil(measuringMenu.size.width)
|
||||
if self.measuredStandardMenuWidthCache.count >= Self.measuredStandardMenuWidthCacheLimit {
|
||||
self.measuredStandardMenuWidthCache.removeAll(keepingCapacity: true)
|
||||
}
|
||||
self.measuredStandardMenuWidthCache[cacheKey] = measured
|
||||
return measured
|
||||
}
|
||||
|
||||
private func measuredStandardMenuWidthCacheKey(
|
||||
for sections: [MenuDescriptor.Section],
|
||||
baseWidth: CGFloat) -> String
|
||||
{
|
||||
var parts = [
|
||||
"base=\(Int((baseWidth * 100).rounded()))",
|
||||
"font=\(Self.menuCardHeightTextScaleToken())",
|
||||
self.menuLocalizationSignature(),
|
||||
]
|
||||
for section in sections {
|
||||
parts.append("[")
|
||||
for entry in section.entries {
|
||||
parts.append(self.measuredStandardMenuWidthCacheToken(for: entry))
|
||||
}
|
||||
parts.append("]")
|
||||
}
|
||||
return parts.joined(separator: "\u{1f}")
|
||||
}
|
||||
|
||||
private func measuredStandardMenuWidthCacheToken(for entry: MenuDescriptor.Entry) -> String {
|
||||
switch entry {
|
||||
case let .text(text, style):
|
||||
"text:\(style):\(text)"
|
||||
case let .action(title, action):
|
||||
"action:\(title):\(self.measuredStandardMenuWidthCacheToken(for: action))"
|
||||
case let .unavailable(title, tooltip):
|
||||
"unavailable:\(title):\(tooltip ?? "")"
|
||||
case let .submenu(title, systemImageName, submenuItems):
|
||||
"submenu:\(title):\(systemImageName ?? ""):" + submenuItems.map { item in
|
||||
[
|
||||
item.title,
|
||||
item.isEnabled ? "1" : "0",
|
||||
item.isChecked ? "1" : "0",
|
||||
item.action.map(self.measuredStandardMenuWidthCacheToken(for:)) ?? "",
|
||||
].joined(separator: ":")
|
||||
}.joined(separator: ",")
|
||||
case .divider:
|
||||
"divider"
|
||||
}
|
||||
}
|
||||
|
||||
private func measuredStandardMenuWidthCacheToken(for action: MenuDescriptor.MenuAction) -> String {
|
||||
switch action {
|
||||
case .installUpdate:
|
||||
"installUpdate"
|
||||
case .refresh:
|
||||
"refresh"
|
||||
case .refreshAugmentSession:
|
||||
"refreshAugmentSession"
|
||||
case .dashboard:
|
||||
"dashboard"
|
||||
case .statusPage:
|
||||
"statusPage"
|
||||
case .changelog:
|
||||
"changelog"
|
||||
case .addCodexAccount:
|
||||
"addCodexAccount:\(self.codexAddAccountSubtitle() ?? "")"
|
||||
case let .requestCodexSystemPromotion(id):
|
||||
"requestCodexSystemPromotion:\(id)"
|
||||
case let .addProviderAccount(provider):
|
||||
"addProviderAccount:\(provider.rawValue)"
|
||||
case let .switchAccount(provider):
|
||||
"switchAccount:\(provider.rawValue):\(self.switchAccountSubtitle(for: provider) ?? "")"
|
||||
case let .openTerminal(command):
|
||||
"openTerminal:\(command)"
|
||||
case let .loginToProvider(url):
|
||||
"loginToProvider:\(url)"
|
||||
case .settings:
|
||||
"settings"
|
||||
case .about:
|
||||
"about"
|
||||
case .quit:
|
||||
"quit"
|
||||
case let .copyError(message):
|
||||
"copyError:\(message)"
|
||||
case let .focusAgentSession(session, remoteHost):
|
||||
"focusAgentSession:\(remoteHost ?? "local"):\(session.id)"
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user