chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,142 @@
|
||||
import AppKit
|
||||
|
||||
struct CachedMergedSwitcherMenuContent {
|
||||
let requiredMenuContentVersion: Int
|
||||
let menuWidth: CGFloat
|
||||
let codexAccountDisplay: CodexAccountMenuDisplay?
|
||||
let tokenAccountDisplay: TokenAccountMenuDisplay?
|
||||
let localizationSignature: String
|
||||
let items: [NSMenuItem]
|
||||
|
||||
func matches(
|
||||
requiredMenuContentVersion: Int,
|
||||
menuWidth: CGFloat,
|
||||
codexAccountDisplay: CodexAccountMenuDisplay?,
|
||||
tokenAccountDisplay: TokenAccountMenuDisplay?,
|
||||
localizationSignature: String)
|
||||
-> Bool
|
||||
{
|
||||
self.requiredMenuContentVersion >= requiredMenuContentVersion &&
|
||||
abs(self.menuWidth - menuWidth) <= 0.5 &&
|
||||
self.codexAccountDisplay == codexAccountDisplay &&
|
||||
self.tokenAccountDisplay == tokenAccountDisplay &&
|
||||
self.localizationSignature == localizationSignature
|
||||
}
|
||||
}
|
||||
|
||||
struct MergedSwitcherContentCacheContext {
|
||||
let menuWidth: CGFloat
|
||||
let codexAccountDisplay: CodexAccountMenuDisplay?
|
||||
let tokenAccountDisplay: TokenAccountMenuDisplay?
|
||||
let contentVersion: Int?
|
||||
}
|
||||
|
||||
extension StatusItemController {
|
||||
func preservingMergedSwitcherContentCachesDuringInvalidation(_ body: () -> Void) {
|
||||
let previous = self.preservesMergedSwitcherContentCachesDuringInvalidation
|
||||
self.preservesMergedSwitcherContentCachesDuringInvalidation = true
|
||||
defer { self.preservesMergedSwitcherContentCachesDuringInvalidation = previous }
|
||||
body()
|
||||
}
|
||||
|
||||
func clearMergedSwitcherContentCaches() {
|
||||
self.mergedSwitcherContentCaches.removeAll(keepingCapacity: true)
|
||||
}
|
||||
|
||||
func clearMergedSwitcherContentCache(for menu: NSMenu) {
|
||||
self.mergedSwitcherContentCaches.removeValue(forKey: ObjectIdentifier(menu))
|
||||
}
|
||||
|
||||
func cacheVisibleMergedSwitcherContent(
|
||||
in menu: NSMenu,
|
||||
selection: ProviderSwitcherSelection,
|
||||
contentStartIndex: Int,
|
||||
menuWidth: CGFloat,
|
||||
contentVersion: Int? = nil)
|
||||
{
|
||||
guard self.shouldMergeIcons else { return }
|
||||
guard menu.items.first?.view is ProviderSwitcherView else { return }
|
||||
guard contentStartIndex < menu.items.count else { return }
|
||||
let items = Array(menu.items[contentStartIndex...])
|
||||
self.cacheMergedSwitcherContent(
|
||||
items,
|
||||
in: menu,
|
||||
selection: selection,
|
||||
context: MergedSwitcherContentCacheContext(
|
||||
menuWidth: menuWidth,
|
||||
codexAccountDisplay: self.lastCodexAccountMenuDisplay,
|
||||
tokenAccountDisplay: self.lastTokenAccountMenuDisplay,
|
||||
contentVersion: contentVersion))
|
||||
}
|
||||
|
||||
func cacheMergedSwitcherContent(
|
||||
_ items: [NSMenuItem],
|
||||
in menu: NSMenu,
|
||||
selection: ProviderSwitcherSelection,
|
||||
context: MergedSwitcherContentCacheContext)
|
||||
{
|
||||
guard !items.isEmpty else { return }
|
||||
|
||||
let entry = CachedMergedSwitcherMenuContent(
|
||||
requiredMenuContentVersion: context.contentVersion ??
|
||||
self.menuSession.renderedVersion(for: ObjectIdentifier(menu)) ??
|
||||
self.menuSession.latestRequiredRebuildVersion,
|
||||
menuWidth: context.menuWidth,
|
||||
codexAccountDisplay: context.codexAccountDisplay,
|
||||
tokenAccountDisplay: context.tokenAccountDisplay,
|
||||
localizationSignature: self.lastMenuLocalizationSignature,
|
||||
items: items)
|
||||
self.mergedSwitcherContentCaches[ObjectIdentifier(menu), default: [:]][selection] = entry
|
||||
}
|
||||
|
||||
/// Returns a reusable cached content block, evicting stale entries without attaching them.
|
||||
func reusableMergedSwitcherContent(
|
||||
for selection: ProviderSwitcherSelection,
|
||||
in menu: NSMenu,
|
||||
menuWidth: CGFloat,
|
||||
codexAccountDisplay: CodexAccountMenuDisplay?,
|
||||
tokenAccountDisplay: TokenAccountMenuDisplay?)
|
||||
-> [NSMenuItem]?
|
||||
{
|
||||
let key = ObjectIdentifier(menu)
|
||||
guard let entry = self.mergedSwitcherContentCaches[key]?[selection] else { return nil }
|
||||
guard entry.matches(
|
||||
requiredMenuContentVersion: self.menuSession.latestRequiredRebuildVersion,
|
||||
menuWidth: menuWidth,
|
||||
codexAccountDisplay: codexAccountDisplay,
|
||||
tokenAccountDisplay: tokenAccountDisplay,
|
||||
localizationSignature: self.menuLocalizationSignature())
|
||||
else {
|
||||
self.mergedSwitcherContentCaches[key]?.removeValue(forKey: selection)
|
||||
return nil
|
||||
}
|
||||
return entry.items
|
||||
}
|
||||
|
||||
func addCachedMergedSwitcherContent(
|
||||
for selection: ProviderSwitcherSelection,
|
||||
to menu: NSMenu,
|
||||
menuWidth: CGFloat,
|
||||
codexAccountDisplay: CodexAccountMenuDisplay?,
|
||||
tokenAccountDisplay: TokenAccountMenuDisplay?)
|
||||
-> Bool
|
||||
{
|
||||
guard let items = self.reusableMergedSwitcherContent(
|
||||
for: selection,
|
||||
in: menu,
|
||||
menuWidth: menuWidth,
|
||||
codexAccountDisplay: codexAccountDisplay,
|
||||
tokenAccountDisplay: tokenAccountDisplay)
|
||||
else { return false }
|
||||
|
||||
self.lastCodexAccountMenuDisplay = codexAccountDisplay
|
||||
self.lastTokenAccountMenuDisplay = tokenAccountDisplay
|
||||
for item in items {
|
||||
menu.addItem(item)
|
||||
}
|
||||
// Detached Refresh items cannot observe a completed manual refresh. Recompute only
|
||||
// after AppKit has restored their menu so provider-scoped busy state is available.
|
||||
self.updatePersistentRefreshItemsEnabled()
|
||||
return true
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user