feat: add destination-specific global shortcuts
This commit is contained in:
@@ -6,15 +6,20 @@ public final class GlobalShortcut {
|
||||
public private(set) var shortcut: KeyboardShortcut?
|
||||
public private(set) var isRegistered = false
|
||||
|
||||
private static let storageKey = "globalActivationShortcut"
|
||||
private let storageKey: String
|
||||
private let defaults: UserDefaults
|
||||
private let action: @MainActor () -> Void
|
||||
private let native = NativeHotKey()
|
||||
|
||||
public init(defaults: UserDefaults = .standard, action: @escaping @MainActor () -> Void) {
|
||||
public init(
|
||||
defaults: UserDefaults = .standard,
|
||||
storageKey: String = "globalActivationShortcut",
|
||||
action: @escaping @MainActor () -> Void
|
||||
) {
|
||||
self.defaults = defaults
|
||||
self.storageKey = storageKey
|
||||
self.action = action
|
||||
shortcut = KeyboardShortcut(storedValue: defaults.object(forKey: Self.storageKey))
|
||||
shortcut = KeyboardShortcut(storedValue: defaults.object(forKey: storageKey))
|
||||
native.owner = self
|
||||
}
|
||||
|
||||
@@ -24,7 +29,7 @@ public final class GlobalShortcut {
|
||||
|
||||
public func start() throws {
|
||||
guard !isRegistered else { return }
|
||||
if let saved = defaults.object(forKey: Self.storageKey) {
|
||||
if let saved = defaults.object(forKey: storageKey) {
|
||||
guard let restored = KeyboardShortcut(storedValue: saved) else {
|
||||
throw ShortcutError.invalidSavedShortcut
|
||||
}
|
||||
@@ -37,11 +42,11 @@ public final class GlobalShortcut {
|
||||
if candidate == shortcut, isRegistered { return }
|
||||
if let candidate {
|
||||
try activate(candidate)
|
||||
defaults.set(candidate.storedValue, forKey: Self.storageKey)
|
||||
defaults.set(candidate.storedValue, forKey: storageKey)
|
||||
} else {
|
||||
try native.unregister()
|
||||
isRegistered = false
|
||||
defaults.removeObject(forKey: Self.storageKey)
|
||||
defaults.removeObject(forKey: storageKey)
|
||||
}
|
||||
shortcut = candidate
|
||||
}
|
||||
@@ -91,17 +96,23 @@ public final class GlobalShortcut {
|
||||
}
|
||||
}
|
||||
|
||||
private enum ShortcutError: LocalizedError {
|
||||
enum ShortcutError: LocalizedError {
|
||||
case invalidSavedShortcut
|
||||
case systemConflict(String)
|
||||
case inAppConflict(shortcut: String, action: String)
|
||||
case duplicate(shortcut: String, destination: String)
|
||||
case native(operation: String, status: OSStatus)
|
||||
|
||||
var errorDescription: String? {
|
||||
switch self {
|
||||
case .invalidSavedShortcut:
|
||||
return "The saved activation shortcut is invalid. Choose a new shortcut or clear it in Conjure Settings."
|
||||
return "The saved shortcut is invalid. Choose a new shortcut or clear it in Conjure Settings."
|
||||
case .systemConflict(let shortcut):
|
||||
return "\(shortcut) is already an enabled macOS shortcut. Free it in System Settings → Keyboard → Keyboard Shortcuts (check Spotlight and Input Sources), or choose another shortcut. Conjure will not change your system settings."
|
||||
case .inAppConflict(let shortcut, let action):
|
||||
return "\(shortcut) is already used by Conjure for \(action). Choose another shortcut."
|
||||
case .duplicate(let shortcut, let destination):
|
||||
return "\(shortcut) is already assigned to \(destination). Clear that binding or choose another shortcut."
|
||||
case .native(let operation, let status):
|
||||
if status == eventHotKeyExistsErr {
|
||||
return "That shortcut is already registered by another app. Change or disable the other app’s shortcut, or choose another one. For Command-Space, also check Spotlight and Input Sources in System Settings → Keyboard → Keyboard Shortcuts."
|
||||
|
||||
Reference in New Issue
Block a user