Refactor Power Mode hotkeys into dedicated PowerModeShortcutManager for cleaner architecture and better observer lifecycle management

This commit is contained in:
Beingpax 2026-01-03 09:47:07 +05:45
parent 78ab6fb3b2
commit f0df362fac
2 changed files with 88 additions and 68 deletions

View File

@ -43,6 +43,7 @@ class HotkeyManager: ObservableObject {
private var whisperState: WhisperState
private var miniRecorderShortcutManager: MiniRecorderShortcutManager
private var powerModeShortcutManager: PowerModeShortcutManager
// MARK: - Helper Properties
private var canProcessHotkeyAction: Bool {
@ -74,8 +75,6 @@ class HotkeyManager: ObservableObject {
private var lastShortcutTriggerTime: Date?
private let shortcutCooldownInterval: TimeInterval = 0.5
private var registeredPowerModeIds: Set<UUID> = []
enum HotkeyOption: String, CaseIterable {
case none = "none"
case rightOption = "rightOption"
@ -129,6 +128,7 @@ class HotkeyManager: ObservableObject {
self.whisperState = whisperState
self.miniRecorderShortcutManager = MiniRecorderShortcutManager(whisperState: whisperState)
self.powerModeShortcutManager = PowerModeShortcutManager(whisperState: whisperState)
KeyboardShortcuts.onKeyUp(for: .pasteLastTranscription) { [weak self] in
guard let self = self else { return }
@ -164,21 +164,6 @@ class HotkeyManager: ObservableObject {
Task { @MainActor in
try? await Task.sleep(nanoseconds: 100_000_000)
self.setupHotkeyMonitoring()
self.setupPowerModeHotkeys()
}
// Observe PowerMode configuration changes
NotificationCenter.default.addObserver(
self,
selector: #selector(powerModeConfigurationsDidChange),
name: NSNotification.Name("PowerModeConfigurationsDidChange"),
object: nil
)
}
@objc private func powerModeConfigurationsDidChange() {
Task { @MainActor in
setupPowerModeHotkeys()
}
}
@ -437,58 +422,8 @@ class HotkeyManager: ObservableObject {
}
deinit {
NotificationCenter.default.removeObserver(self)
Task { @MainActor in
removeAllMonitoring()
}
}
}
// MARK: - PowerMode Hotkey Management
extension HotkeyManager {
func setupPowerModeHotkeys() {
let powerModesWithShortcuts = Set(PowerModeManager.shared.configurations
.filter { $0.hotkeyShortcut != nil }
.map { $0.id })
let idsToRemove = registeredPowerModeIds.subtracting(powerModesWithShortcuts)
idsToRemove.forEach { id in
KeyboardShortcuts.setShortcut(nil, for: .powerMode(id: id))
KeyboardShortcuts.disable(.powerMode(id: id))
registeredPowerModeIds.remove(id)
}
PowerModeManager.shared.configurations.forEach { config in
guard config.hotkeyShortcut != nil else { return }
guard !registeredPowerModeIds.contains(config.id) else { return }
KeyboardShortcuts.onKeyUp(for: .powerMode(id: config.id)) { [weak self] in
guard let self = self else { return }
Task { @MainActor in
await self.handlePowerModeHotkey(powerModeId: config.id)
}
}
registeredPowerModeIds.insert(config.id)
}
}
private func handlePowerModeHotkey(powerModeId: UUID) async {
guard canProcessHotkeyAction else { return }
guard let config = PowerModeManager.shared.getConfiguration(with: powerModeId),
config.hotkeyShortcut != nil else {
return
}
await whisperState.toggleMiniRecorder(powerModeId: powerModeId)
}
}
// MARK: - PowerMode Keyboard Shortcut Names
extension KeyboardShortcuts.Name {
static func powerMode(id: UUID) -> Self {
Self("powerMode_\(id.uuidString)")
}
}
}

View File

@ -0,0 +1,85 @@
import Foundation
import KeyboardShortcuts
@MainActor
class PowerModeShortcutManager {
private weak var whisperState: WhisperState?
private var registeredPowerModeIds: Set<UUID> = []
init(whisperState: WhisperState) {
self.whisperState = whisperState
setupPowerModeHotkeys()
NotificationCenter.default.addObserver(
self,
selector: #selector(powerModeConfigurationsDidChange),
name: NSNotification.Name("PowerModeConfigurationsDidChange"),
object: nil
)
}
deinit {
NotificationCenter.default.removeObserver(self)
}
@objc private func powerModeConfigurationsDidChange() {
Task { @MainActor in
setupPowerModeHotkeys()
}
}
private func setupPowerModeHotkeys() {
let powerModesWithShortcuts = Set(PowerModeManager.shared.configurations
.filter { $0.hotkeyShortcut != nil }
.map { $0.id })
// Remove shortcuts for deleted or updated configs
let idsToRemove = registeredPowerModeIds.subtracting(powerModesWithShortcuts)
idsToRemove.forEach { id in
KeyboardShortcuts.setShortcut(nil, for: .powerMode(id: id))
KeyboardShortcuts.disable(.powerMode(id: id))
registeredPowerModeIds.remove(id)
}
// Add new shortcuts
PowerModeManager.shared.configurations.forEach { config in
guard config.hotkeyShortcut != nil else { return }
guard !registeredPowerModeIds.contains(config.id) else { return }
KeyboardShortcuts.onKeyUp(for: .powerMode(id: config.id)) { [weak self] in
guard let self = self else { return }
Task { @MainActor in
await self.handlePowerModeHotkey(powerModeId: config.id)
}
}
registeredPowerModeIds.insert(config.id)
}
}
private func handlePowerModeHotkey(powerModeId: UUID) async {
guard let whisperState = whisperState,
canProcessHotkeyAction(whisperState: whisperState) else { return }
guard let config = PowerModeManager.shared.getConfiguration(with: powerModeId),
config.hotkeyShortcut != nil else {
return
}
await whisperState.toggleMiniRecorder(powerModeId: powerModeId)
}
private func canProcessHotkeyAction(whisperState: WhisperState) -> Bool {
whisperState.recordingState != .transcribing &&
whisperState.recordingState != .enhancing &&
whisperState.recordingState != .busy
}
}
// MARK: - PowerMode Keyboard Shortcut Names
extension KeyboardShortcuts.Name {
static func powerMode(id: UUID) -> Self {
Self("powerMode_\(id.uuidString)")
}
}