Skip to content

Commit ef8f5c9

Browse files
committed
deal with bug in KeyboardShortcuts
1 parent 32f8267 commit ef8f5c9

File tree

4 files changed

+61
-25
lines changed

4 files changed

+61
-25
lines changed

app/modules/App/Sources/Windows/WindowsViewModel.swift

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,8 @@ final class WindowsViewModel {
1818
init() {
1919
state = .init(isSidePanelVisible: false, isSetupVisible: false)
2020

21-
Task {
22-
await appEventHandlerRegistry.registerHandler { [weak self] event in
23-
await self?.handle(appEvent: event) ?? false
24-
}
21+
appEventHandlerRegistry.registerHandler { [weak self] event in
22+
await self?.handle(appEvent: event) ?? false
2523
}
2624
permissionsService.status(for: .accessibility).sink { [weak self] isGranted in
2725
self?.handle(.accessibilityPermissionChanged(isGranted: isGranted))

app/modules/App/Sources/XcodeKeyboardShortcuts.swift

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,30 +23,47 @@ final class XcodeKeyboardShortcutsManager: @unchecked Sendable {
2323

2424
private var cancellables: Set<AnyCancellable> = []
2525

26+
private var enabledShortcutNames = Set<String>()
27+
2628
@Dependency(\.appEventHandlerRegistry) private var appEventHandlerRegistry
2729

2830
/// This can be moved to the initializer once https://github.com/swiftlang/swift/issues/80050 is fixed.
2931
private func observeXcodeState(appsActivationState: AnyPublisher<AppsActivationState, Never>) {
3032
let cancellable = appsActivationState
3133
.sink { @Sendable [weak self] appsActivationState in
32-
guard self != nil else { return }
34+
guard let self else { return }
3335
// Handle de-activations first, then activations.
3436
if !appsActivationState.isHostAppActive {
35-
KeyboardShortcuts.disable(KeyboardShortcuts.Name.hostAppShortcuts)
37+
disable(KeyboardShortcuts.Name.hostAppShortcuts)
3638
}
3739
if !appsActivationState.isXcodeActive {
38-
KeyboardShortcuts.disable(KeyboardShortcuts.Name.xcodeShortcuts)
40+
disable(KeyboardShortcuts.Name.xcodeShortcuts)
3941
}
4042
if appsActivationState.isHostAppActive {
41-
KeyboardShortcuts.enable(KeyboardShortcuts.Name.hostAppShortcuts)
43+
enable(KeyboardShortcuts.Name.hostAppShortcuts)
4244
}
4345
if appsActivationState.isXcodeActive {
44-
KeyboardShortcuts.enable(KeyboardShortcuts.Name.xcodeShortcuts)
46+
enable(KeyboardShortcuts.Name.xcodeShortcuts)
4547
}
4648
}
4749
safelyMutate { $0.cancellables.insert(cancellable) }
4850
}
4951

52+
/// Manually tracks enabled shortcuts due to https://github.com/sindresorhus/KeyboardShortcuts/issues/217
53+
private func enable(_ shortcuts: [KeyboardShortcuts.Name]) {
54+
KeyboardShortcuts.enable(shortcuts)
55+
safelyMutate { state in
56+
for shortcut in shortcuts { state.enabledShortcutNames.insert(shortcut.rawValue) }
57+
}
58+
}
59+
60+
private func disable(_ shortcuts: [KeyboardShortcuts.Name]) {
61+
KeyboardShortcuts.disable(shortcuts)
62+
safelyMutate { state in
63+
for shortcut in shortcuts { state.enabledShortcutNames.remove(shortcut.rawValue) }
64+
}
65+
}
66+
5067
private func registerActions() {
5168
on(.ask, trigger: AddCodeToChatEvent(newThread: false, chatMode: .ask))
5269
on(.askInNewThread, trigger: AddCodeToChatEvent(newThread: true, chatMode: .ask))
@@ -56,14 +73,17 @@ final class XcodeKeyboardShortcutsManager: @unchecked Sendable {
5673
on(.generate, trigger: GenerateEvent())
5774
on(.hideChat, trigger: HideChatEvent())
5875
on(.new, trigger: NewChatEvent())
59-
on(.switchToAskMode, trigger: AddCodeToChatEvent(newThread: false, chatMode: .ask))
60-
on(.switchToAgentMode, trigger: AddCodeToChatEvent(newThread: false, chatMode: .agent))
76+
on(.switchToAskMode, trigger: ChangeChatModeEvent(chatMode: .ask))
77+
on(.switchToAgentMode, trigger: ChangeChatModeEvent(chatMode: .agent))
6178
}
6279

6380
private func on(_ keyEvent: KeyboardShortcuts.Name, trigger event: AppEvent) {
6481
KeyboardShortcuts.onKeyUp(for: keyEvent) {
6582
Task { [weak self] in
66-
await self?.appEventHandlerRegistry.handle(event: event)
83+
guard let self else { return }
84+
if enabledShortcutNames.contains(keyEvent.rawValue) {
85+
_ = await appEventHandlerRegistry.handle(event: event)
86+
}
6787
}
6888
}
6989
}

app/modules/features/Chat/Sources/ChatViewModel.swift

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -53,19 +53,7 @@ public class ChatViewModel {
5353
self.currentModel = currentModel
5454
self.selectedTab = selectedTab
5555
self.defaultMode = defaultMode
56-
57-
appEventHandlerRegistry.registerHandler { [weak self] event in
58-
guard let self else { return false }
59-
if let event = event as? AddCodeToChatEvent {
60-
await handle(addCodeToChatEvent: event)
61-
return true
62-
} else if event is NewChatEvent {
63-
await addTab(copyingCurrentInput: true)
64-
return true
65-
} else {
66-
return false
67-
}
68-
}
56+
registerAsAppEventHandler()
6957
}
7058

7159
var tabs: [ChatTabViewModel]
@@ -106,6 +94,26 @@ public class ChatViewModel {
10694
@ObservationIgnored @Dependency(\.xcodeObserver) private var xcodeObserver
10795
@ObservationIgnored @Dependency(\.fileManager) private var fileManager
10896

97+
private func registerAsAppEventHandler() {
98+
appEventHandlerRegistry.registerHandler { [weak self] event in
99+
guard let self else { return false }
100+
if let event = event as? AddCodeToChatEvent {
101+
await handle(addCodeToChatEvent: event)
102+
return true //
103+
} else if let event = event as? ChangeChatModeEvent {
104+
Task { @MainActor in
105+
self.selectedTab?.input.mode = event.chatMode
106+
}
107+
return true
108+
} else if event is NewChatEvent {
109+
await addTab(copyingCurrentInput: true)
110+
return true
111+
} else {
112+
return false
113+
}
114+
}
115+
}
116+
109117
private func handle(addCodeToChatEvent event: AddCodeToChatEvent) {
110118
Task { @MainActor in
111119
if ProcessInfo.processInfo.processName != "xctest" {

app/modules/foundations/ChatAppEvents/Sources/ChatAppEvents.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,16 @@ public struct AddCodeToChatEvent: AppEvent {
1616
public let chatMode: ChatMode?
1717
}
1818

19+
// MARK: - ChangeChatModeEvent
20+
21+
public struct ChangeChatModeEvent: AppEvent {
22+
public init(chatMode: ChatMode) {
23+
self.chatMode = chatMode
24+
}
25+
26+
public let chatMode: ChatMode
27+
}
28+
1929
// MARK: - NewChatEvent
2030

2131
public struct NewChatEvent: AppEvent {

0 commit comments

Comments
 (0)