forked from intitni/CopilotForXcode
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathService.swift
More file actions
137 lines (116 loc) · 4.1 KB
/
Service.swift
File metadata and controls
137 lines (116 loc) · 4.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
import AppKit
import Combine
import Dependencies
import Foundation
import KeyboardShortcuts
import Workspace
import WorkspaceSuggestionService
import XcodeInspector
#if canImport(ProService)
import ProService
#endif
@globalActor public enum ServiceActor {
public actor TheActor {}
public static let shared = TheActor()
}
extension KeyboardShortcuts.Name {
static let showHideWidget = Self("ShowHideWidget")
}
/// The running extension service.
public final class Service {
public static let shared = Service()
@WorkspaceActor
let workspacePool: WorkspacePool
@MainActor
public let guiController = GraphicalUserInterfaceController()
public let realtimeSuggestionController = RealtimeSuggestionController()
public let scheduledCleaner: ScheduledCleaner
let globalShortcutManager: GlobalShortcutManager
#if canImport(ProService)
let proService: ProService
#endif
private init() {
@Dependency(\.workspacePool) var workspacePool
scheduledCleaner = .init()
workspacePool.registerPlugin { SuggestionServiceWorkspacePlugin(workspace: $0) }
self.workspacePool = workspacePool
globalShortcutManager = .init(guiController: guiController)
#if canImport(ProService)
proService = withDependencies { dependencyValues in
dependencyValues.proServiceAcceptSuggestion = {
Task { await PseudoCommandHandler().acceptSuggestion() }
}
} operation: {
ProService()
}
#endif
scheduledCleaner.service = self
}
@MainActor
public func start() {
scheduledCleaner.start()
realtimeSuggestionController.start()
guiController.start()
#if canImport(ProService)
proService.start()
#endif
DependencyUpdater().update()
globalShortcutManager.start()
}
}
@MainActor
final class GlobalShortcutManager {
let guiController: GraphicalUserInterfaceController
private var cancellable = Set<AnyCancellable>()
nonisolated init(guiController: GraphicalUserInterfaceController) {
self.guiController = guiController
}
func start() {
KeyboardShortcuts.userDefaults = .shared
setupShortcutIfNeeded()
KeyboardShortcuts.onKeyUp(for: .showHideWidget) { [guiController] in
let isXCodeActive = XcodeInspector.shared.activeXcode != nil
let isExtensionActive = NSApplication.shared.isActive
if !isXCodeActive,
!guiController.viewStore.state.suggestionWidgetState.chatPanelState.isPanelDisplayed,
UserDefaults.shared.value(for: \.showHideWidgetShortcutGlobally)
{
guiController.viewStore.send(.openChatPanel(forceDetach: true))
} else {
guiController.viewStore.send(.suggestionWidget(.circularWidget(.widgetClicked)))
}
if !isExtensionActive {
Task {
try await Task.sleep(nanoseconds: 150_000_000)
NSApplication.shared.activate(ignoringOtherApps: true)
}
} else if let previous = XcodeInspector.shared.previousActiveApplication,
!previous.isActive
{
previous.runningApplication.activate()
}
}
XcodeInspector.shared.$activeApplication.sink { app in
if !UserDefaults.shared.value(for: \.showHideWidgetShortcutGlobally) {
let shouldBeEnabled = if let app, app.isXcode || app.isExtensionService {
true
} else {
false
}
if shouldBeEnabled {
self.setupShortcutIfNeeded()
} else {
self.removeShortcutIfNeeded()
}
} else {
self.setupShortcutIfNeeded()
}
}.store(in: &cancellable)
}
func setupShortcutIfNeeded() {
KeyboardShortcuts.enable(.showHideWidget)
}
func removeShortcutIfNeeded() {
KeyboardShortcuts.disable(.showHideWidget)
}
}