Skip to content

Commit 3bc2c86

Browse files
committed
Add CursorPositionTracker
1 parent 3257f5f commit 3bc2c86

File tree

2 files changed

+56
-2
lines changed

2 files changed

+56
-2
lines changed
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import Combine
2+
import Foundation
3+
import Perception
4+
import SuggestionModel
5+
import XcodeInspector
6+
7+
@Perceptible
8+
final class CursorPositionTracker {
9+
@MainActor
10+
var cursorPosition: CursorPosition = .zero
11+
12+
@PerceptionIgnored var editorObservationTask: Set<AnyCancellable> = []
13+
@PerceptionIgnored var eventObservationTask: Task<Void, Never>?
14+
15+
init() {
16+
observeAppChange()
17+
}
18+
19+
deinit {
20+
eventObservationTask?.cancel()
21+
}
22+
23+
private func observeAppChange() {
24+
editorObservationTask = []
25+
Task {
26+
await XcodeInspector.shared.safe.$focusedEditor.sink { [weak self] editor in
27+
guard let editor, let self else { return }
28+
Task { @MainActor in
29+
self.observeAXNotifications(editor)
30+
}
31+
}.store(in: &editorObservationTask)
32+
}
33+
}
34+
35+
private func observeAXNotifications(_ editor: SourceEditor) {
36+
eventObservationTask?.cancel()
37+
let content = editor.getLatestEvaluatedContent()
38+
Task { @MainActor in
39+
self.cursorPosition = content.cursorPosition
40+
}
41+
eventObservationTask = Task { [weak self] in
42+
for await event in await editor.axNotifications.notifications() {
43+
guard let self else { return }
44+
guard event.kind == .evaluatedContentChanged else { continue }
45+
let content = editor.getLatestEvaluatedContent()
46+
Task { @MainActor in
47+
self.cursorPosition = content.cursorPosition
48+
}
49+
}
50+
}
51+
}
52+
}
53+

Core/Sources/SuggestionWidget/WidgetWindowsController.swift

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -599,6 +599,7 @@ public final class WidgetWindows {
599599
let store: StoreOf<WidgetFeature>
600600
let chatTabPool: ChatTabPool
601601
weak var controller: WidgetWindowsController?
602+
let cursorPositionTracker = CursorPositionTracker()
602603

603604
// you should make these window `.transient` so they never show up in the mission control.
604605

@@ -670,7 +671,7 @@ public final class WidgetWindows {
670671
state: \.sharedPanelState,
671672
action: \.sharedPanel
672673
)
673-
)
674+
).environment(cursorPositionTracker)
674675
)
675676
it.setIsVisible(true)
676677
it.canBecomeKeyChecker = { [store] in
@@ -704,7 +705,7 @@ public final class WidgetWindows {
704705
state: \.suggestionPanelState,
705706
action: \.suggestionPanel
706707
)
707-
)
708+
).environment(cursorPositionTracker)
708709
)
709710
it.canBecomeKeyChecker = { false }
710711
it.setIsVisible(true)

0 commit comments

Comments
 (0)