chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,107 @@
|
||||
import AppKit
|
||||
|
||||
enum StatusItemMenuProviderNavigationDirection {
|
||||
case previous
|
||||
case next
|
||||
}
|
||||
|
||||
protocol StatusItemMenuPersistentActionDelegate: AnyObject {
|
||||
func performPersistentRefreshAction(
|
||||
in menuID: ObjectIdentifier,
|
||||
menuInteractionGeneration: Int)
|
||||
func performPersistentSettingsAction()
|
||||
func performPersistentQuitAction()
|
||||
func performProviderNavigation(_ direction: StatusItemMenuProviderNavigationDirection)
|
||||
}
|
||||
|
||||
final class StatusItemMenu: NSMenu {
|
||||
weak var persistentActionDelegate: StatusItemMenuPersistentActionDelegate?
|
||||
var menuInteractionGeneration: Int?
|
||||
|
||||
func requestPersistentRefreshAction() {
|
||||
guard let menuInteractionGeneration else { return }
|
||||
self.persistentActionDelegate?.performPersistentRefreshAction(
|
||||
in: ObjectIdentifier(self),
|
||||
menuInteractionGeneration: menuInteractionGeneration)
|
||||
}
|
||||
|
||||
override func performKeyEquivalent(with event: NSEvent) -> Bool {
|
||||
if let action = Self.persistentAction(for: event) {
|
||||
switch action {
|
||||
case .refresh:
|
||||
self.requestPersistentRefreshAction()
|
||||
case .settings:
|
||||
self.persistentActionDelegate?.performPersistentSettingsAction()
|
||||
case .quit:
|
||||
self.persistentActionDelegate?.performPersistentQuitAction()
|
||||
}
|
||||
return true
|
||||
}
|
||||
if let direction = Self.providerNavigationDirection(for: event),
|
||||
self.items.first?.view is ProviderSwitcherView
|
||||
{
|
||||
self.persistentActionDelegate?.performProviderNavigation(direction)
|
||||
return true
|
||||
}
|
||||
|
||||
return super.performKeyEquivalent(with: event)
|
||||
}
|
||||
|
||||
private enum PersistentAction {
|
||||
case refresh
|
||||
case settings
|
||||
case quit
|
||||
}
|
||||
|
||||
nonisolated static func isPersistentRefreshShortcut(for event: NSEvent) -> Bool {
|
||||
self.persistentAction(for: event) == .refresh
|
||||
}
|
||||
|
||||
private nonisolated static func persistentAction(for event: NSEvent) -> PersistentAction? {
|
||||
guard event.type == .keyDown else { return nil }
|
||||
|
||||
let relevantModifiers = event.modifierFlags.intersection([.command, .option, .control, .shift])
|
||||
guard relevantModifiers == .command else { return nil }
|
||||
|
||||
switch event.charactersIgnoringModifiers?.lowercased() {
|
||||
case "r":
|
||||
return .refresh
|
||||
case ",":
|
||||
return .settings
|
||||
case "q":
|
||||
return .quit
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
nonisolated static func providerNavigationDirection(
|
||||
for event: NSEvent) -> StatusItemMenuProviderNavigationDirection?
|
||||
{
|
||||
guard event.type == .keyDown else { return nil }
|
||||
let relevantModifiers = event.modifierFlags.intersection([.command, .option, .control, .shift])
|
||||
guard relevantModifiers.isEmpty else { return nil }
|
||||
switch event.keyCode {
|
||||
case 123:
|
||||
return .previous
|
||||
case 124:
|
||||
return .next
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
nonisolated static func providerSelectionIndex(for event: NSEvent) -> Int? {
|
||||
guard event.type == .keyDown else { return nil }
|
||||
let relevantModifiers = event.modifierFlags.intersection([.command, .option, .control, .shift])
|
||||
guard relevantModifiers == .command,
|
||||
let characters = event.charactersIgnoringModifiers,
|
||||
characters.count == 1,
|
||||
let number = Int(characters),
|
||||
(1...9).contains(number)
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
return number - 1
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user