refactor: centralize shortcut recording lifetime
This commit is contained in:
@@ -10,6 +10,18 @@ public final class GlobalShortcut {
|
||||
private let defaults: UserDefaults
|
||||
private let action: @MainActor () -> Void
|
||||
private let native = NativeHotKey()
|
||||
private var registration: Registration?
|
||||
|
||||
struct Registration {
|
||||
var activate: (KeyboardShortcut) throws -> Void
|
||||
var unregister: () throws -> Void
|
||||
var stop: () -> Void
|
||||
}
|
||||
|
||||
convenience init(defaults: UserDefaults, storageKey: String, registration: Registration) {
|
||||
self.init(defaults: defaults, storageKey: storageKey, action: {})
|
||||
self.registration = registration
|
||||
}
|
||||
|
||||
public init(
|
||||
defaults: UserDefaults = .standard,
|
||||
@@ -44,7 +56,7 @@ public final class GlobalShortcut {
|
||||
try activate(candidate)
|
||||
defaults.set(candidate.storedValue, forKey: storageKey)
|
||||
} else {
|
||||
try native.unregister()
|
||||
try unregister()
|
||||
isRegistered = false
|
||||
defaults.removeObject(forKey: storageKey)
|
||||
}
|
||||
@@ -53,7 +65,7 @@ public final class GlobalShortcut {
|
||||
|
||||
public func suspend() {
|
||||
do {
|
||||
try native.unregister()
|
||||
try unregister()
|
||||
isRegistered = false
|
||||
} catch {
|
||||
NSLog("Conjure could not suspend its shortcut: %@", error.localizedDescription)
|
||||
@@ -61,7 +73,7 @@ public final class GlobalShortcut {
|
||||
}
|
||||
|
||||
public func stop() {
|
||||
native.dispose()
|
||||
if let registration { registration.stop() } else { native.dispose() }
|
||||
isRegistered = false
|
||||
}
|
||||
|
||||
@@ -69,9 +81,17 @@ public final class GlobalShortcut {
|
||||
action()
|
||||
}
|
||||
|
||||
private func unregister() throws {
|
||||
if let registration { try registration.unregister() } else { try native.unregister() }
|
||||
}
|
||||
|
||||
private func activate(_ candidate: KeyboardShortcut) throws {
|
||||
try Self.rejectSystemConflict(candidate)
|
||||
try native.register(candidate)
|
||||
if let registration {
|
||||
try registration.activate(candidate)
|
||||
} else {
|
||||
try Self.rejectSystemConflict(candidate)
|
||||
try native.register(candidate)
|
||||
}
|
||||
isRegistered = true
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,13 @@ public final class GlobalShortcuts {
|
||||
public let bindings: [GlobalShortcut]
|
||||
private let defaults: UserDefaults
|
||||
private var isSuspended = false
|
||||
public var isRecording: Bool { isSuspended }
|
||||
|
||||
init(defaults: UserDefaults, bindings: [GlobalShortcut]) {
|
||||
precondition(bindings.count == Self.destinations.count)
|
||||
self.defaults = defaults
|
||||
self.bindings = bindings
|
||||
}
|
||||
|
||||
public init(
|
||||
defaults: UserDefaults = .standard,
|
||||
@@ -60,11 +67,23 @@ public final class GlobalShortcuts {
|
||||
return errors
|
||||
}
|
||||
|
||||
public func suspend() {
|
||||
public func beginRecording() {
|
||||
isSuspended = true
|
||||
bindings.forEach { $0.suspend() }
|
||||
}
|
||||
|
||||
public func cancelRecording() -> [String] {
|
||||
guard isRecording else { return [] }
|
||||
return start()
|
||||
}
|
||||
|
||||
public func finishRecording(_ candidate: KeyboardShortcut?, at index: Int) -> [String] {
|
||||
var errors: [String] = []
|
||||
do { try setShortcut(candidate, at: index) }
|
||||
catch { errors.append(error.localizedDescription) }
|
||||
return errors + cancelRecording()
|
||||
}
|
||||
|
||||
public func stop() {
|
||||
isSuspended = false
|
||||
bindings.forEach { $0.stop() }
|
||||
|
||||
Reference in New Issue
Block a user