import AppKitextension StatusItemController { func usesPersistentMenuActionItem(for action: MenuDescriptor.MenuAction) -> Bool { switch action { case .installUpdate, .refresh, .settings, .about, .quit: true default: false } } func persistentMenuActionSystemImageName(for action: MenuDescriptor.MenuAction) -> String? { switch action { case .installUpdate: "arrow.down.circle" case .refresh: MenuDescriptor.MenuActionSystemImage.refresh.rawValue case .settings: MenuDescriptor.MenuActionSystemImage.settings.rawValue case .about: MenuDescriptor.MenuActionSystemImage.about.rawValue case .quit: MenuDescriptor.MenuActionSystemImage.quit.rawValue default: action.systemImageName } } func performPersistentMenuAction(_ action: MenuDescriptor.MenuAction, in menu: NSMenu?) { switch action { case .refresh: self.refreshNow() case .installUpdate: self.closeMenuForPersistentAction(menu) self.installUpdate() case .settings: self.closeMenuForPersistentAction(menu) self.showSettingsGeneral() case .about: self.closeMenuForPersistentAction(menu) self.showSettingsAbout() case .quit: self.closeMenuForPersistentAction(menu) self.quit() default: break } } /// Syncs every live persistent Refresh row's spinner to the refresh lifecycle. This is /// an in-place AppKit mutation on the existing row views — it never rebuilds the menu, so it /// is safe to call during NSMenu tracking. func updatePersistentRefreshRowsInProgress() { let inProgress = self.manualRefreshTask != nil || self.store.isRefreshing for row in self.persistentRefreshRows.allObjects { row.setInProgress(inProgress) } } private func closeMenuForPersistentAction(_ menu: NSMenu?) { guard let menu else { return } menu.cancelTrackingWithoutAnimation() self.forgetClosedMenu(menu) }}
import AppKit
extension StatusItemController {
func usesPersistentMenuActionItem(for action: MenuDescriptor.MenuAction) -> Bool {
switch action {
case .installUpdate, .refresh, .settings, .about, .quit:
true
default:
false
}
}
func persistentMenuActionSystemImageName(for action: MenuDescriptor.MenuAction) -> String? {
switch action {
case .installUpdate:
"arrow.down.circle"
case .refresh:
MenuDescriptor.MenuActionSystemImage.refresh.rawValue
case .settings:
MenuDescriptor.MenuActionSystemImage.settings.rawValue
case .about:
MenuDescriptor.MenuActionSystemImage.about.rawValue
case .quit:
MenuDescriptor.MenuActionSystemImage.quit.rawValue
default:
action.systemImageName
}
}
func performPersistentMenuAction(_ action: MenuDescriptor.MenuAction, in menu: NSMenu?) {
switch action {
case .refresh:
self.refreshNow()
case .installUpdate:
self.closeMenuForPersistentAction(menu)
self.installUpdate()
case .settings:
self.closeMenuForPersistentAction(menu)
self.showSettingsGeneral()
case .about:
self.closeMenuForPersistentAction(menu)
self.showSettingsAbout()
case .quit:
self.closeMenuForPersistentAction(menu)
self.quit()
default:
break
}
}
/// Syncs every live persistent Refresh row's spinner to the refresh lifecycle. This is
/// an in-place AppKit mutation on the existing row views — it never rebuilds the menu, so it
/// is safe to call during NSMenu tracking.
func updatePersistentRefreshRowsInProgress() {
let inProgress = self.manualRefreshTask != nil || self.store.isRefreshing
for row in self.persistentRefreshRows.allObjects {
row.setInProgress(inProgress)
}
}
private func closeMenuForPersistentAction(_ menu: NSMenu?) {
guard let menu else { return }
menu.cancelTrackingWithoutAnimation()
self.forgetClosedMenu(menu)
}
}