Skip to content

Commit f6c944b

Browse files
committed
Add a warning for accepting suggestion with fallback solution
1 parent a7d3682 commit f6c944b

File tree

1 file changed

+46
-11
lines changed

1 file changed

+46
-11
lines changed

Core/Sources/Service/SuggestionCommandHandler/PseudoCommandHandler.swift

Lines changed: 46 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import AppKit
33
import Preferences
44
import SuggestionInjector
55
import SuggestionModel
6+
import Toast
67
import Workspace
78
import WorkspaceSuggestionService
89
import XcodeInspector
@@ -12,6 +13,9 @@ import XPCShared
1213
///
1314
/// For example, we can use it to generate real-time suggestions without Apple Scripts.
1415
struct PseudoCommandHandler {
16+
static var lastTimeCommandFailedToTriggerWithAccessibilityAPI = Date(timeIntervalSince1970: 0)
17+
private var toast: ToastController { ToastControllerDependencyKey.liveValue }
18+
1519
func presentPreviousSuggestion() async {
1620
let handler = WindowBaseCommandHandler()
1721
_ = try? await handler.presentPreviousSuggestion(editor: .init(
@@ -43,11 +47,11 @@ struct PseudoCommandHandler {
4347
@WorkspaceActor
4448
func generateRealtimeSuggestions(sourceEditor: SourceEditor?) async {
4549
guard let filespace = await getFilespace(),
46-
let (workspace, _) = try? await Service.shared.workspacePool
47-
.fetchOrCreateWorkspaceAndFilespace(fileURL: filespace.fileURL) else { return }
48-
50+
let (workspace, _) = try? await Service.shared.workspacePool
51+
.fetchOrCreateWorkspaceAndFilespace(fileURL: filespace.fileURL) else { return }
52+
4953
if Task.isCancelled { return }
50-
54+
5155
// Can't use handler if content is not available.
5256
guard let editor = await getEditorContent(sourceEditor: sourceEditor)
5357
else { return }
@@ -107,7 +111,7 @@ struct PseudoCommandHandler {
107111
if filespace.presentingSuggestion == nil {
108112
return // skip if there's no suggestion presented.
109113
}
110-
114+
111115
let content = sourceEditor.getContent()
112116
if !filespace.validateSuggestions(
113117
lines: content.lines,
@@ -178,8 +182,23 @@ struct PseudoCommandHandler {
178182
if UserDefaults.shared.value(for: \.alwaysAcceptSuggestionWithAccessibilityAPI) {
179183
throw CancellationError()
180184
}
181-
try await XcodeInspector.shared.latestActiveXcode?
182-
.triggerCopilotCommand(name: "Accept Prompt to Code")
185+
do {
186+
try await XcodeInspector.shared.latestActiveXcode?
187+
.triggerCopilotCommand(name: "Accept Prompt to Code")
188+
} catch {
189+
let last = Self.lastTimeCommandFailedToTriggerWithAccessibilityAPI
190+
let now = Date()
191+
if now.timeIntervalSince(last) > 60 * 60 {
192+
Self.lastTimeCommandFailedToTriggerWithAccessibilityAPI = now
193+
toast.toast(content: """
194+
The app is using a fallback solution to accept suggestions. \
195+
For better experience, please restart Xcode to re-activate the Copilot \
196+
menu item.
197+
""", type: .warning)
198+
}
199+
200+
throw error
201+
}
183202
} catch {
184203
guard let xcode = ActiveApplicationMonitor.shared.activeXcode
185204
?? ActiveApplicationMonitor.shared.latestXcode else { return }
@@ -218,8 +237,23 @@ struct PseudoCommandHandler {
218237
if UserDefaults.shared.value(for: \.alwaysAcceptSuggestionWithAccessibilityAPI) {
219238
throw CancellationError()
220239
}
221-
try await XcodeInspector.shared.latestActiveXcode?
222-
.triggerCopilotCommand(name: "Accept Suggestion")
240+
do {
241+
try await XcodeInspector.shared.latestActiveXcode?
242+
.triggerCopilotCommand(name: "Accept Suggestion")
243+
} catch {
244+
let last = Self.lastTimeCommandFailedToTriggerWithAccessibilityAPI
245+
let now = Date()
246+
if now.timeIntervalSince(last) > 60 * 60 {
247+
Self.lastTimeCommandFailedToTriggerWithAccessibilityAPI = now
248+
toast.toast(content: """
249+
The app is using a fallback solution to accept suggestions. \
250+
For better experience, please restart Xcode to re-activate the Copilot \
251+
menu item.
252+
""", type: .warning)
253+
}
254+
255+
throw error
256+
}
223257
} catch {
224258
guard let xcode = ActiveApplicationMonitor.shared.activeXcode
225259
?? ActiveApplicationMonitor.shared.latestXcode else { return }
@@ -252,12 +286,12 @@ struct PseudoCommandHandler {
252286
}
253287
}
254288
}
255-
289+
256290
func dismissSuggestion() async {
257291
guard let documentURL = XcodeInspector.shared.activeDocumentURL else { return }
258292
guard let (_, filespace) = try? await Service.shared.workspacePool
259293
.fetchOrCreateWorkspaceAndFilespace(fileURL: documentURL) else { return }
260-
294+
261295
await filespace.reset()
262296
PresentInWindowSuggestionPresenter().discardSuggestion(fileURL: documentURL)
263297
}
@@ -432,3 +466,4 @@ extension PseudoCommandHandler {
432466
return cursorRange
433467
}
434468
}
469+

0 commit comments

Comments
 (0)