-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Expand file tree
/
Copy pathWidgetWindowsController+FixErrorPanel.swift
More file actions
110 lines (94 loc) · 3.79 KB
/
WidgetWindowsController+FixErrorPanel.swift
File metadata and controls
110 lines (94 loc) · 3.79 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
import AppKit
import XcodeInspector
import Preferences
extension WidgetWindowsController {
@MainActor
var isFixErrorEnabled: Bool {
UserDefaults.shared.value(for: \.enableFixError)
}
@MainActor
func hideFixErrorWindow() {
windows.fixErrorPanelWindow.alphaValue = 0
windows.fixErrorPanelWindow.setIsVisible(false)
}
@MainActor
func displayFixErrorWindow() {
windows.fixErrorPanelWindow.setIsVisible(true)
windows.fixErrorPanelWindow.alphaValue = 1
windows.fixErrorPanelWindow.orderFrontRegardless()
}
func setupFixErrorPanelObservers() {
Task { @MainActor in
let errorAnnotationsPublisher = store.publisher
.map(\.fixErrorPanelState.errorAnnotationsAtCursorPosition)
.removeDuplicates()
.sink { [weak self] _ in
Task { [weak self] in
await self?.updateFixErrorPanelWindowLocation()
}
}
let isPanelDisplayedPublisher = store.publisher
.map(\.fixErrorPanelState.isPanelDisplayed)
.removeDuplicates()
.sink { [weak self ] _ in
Task { [weak self] in
await self?.updateFixErrorPanelWindowLocation()
}
}
await self.storeCancellables([errorAnnotationsPublisher, isPanelDisplayedPublisher])
}
}
@MainActor
func updateFixErrorPanelWindowLocation() async {
guard isFixErrorEnabled else {
hideFixErrorWindow()
return
}
guard let activeApp = await XcodeInspector.shared.safe.activeApplication,
(activeApp.isXcode || activeApp.isCopilotForXcodeExtensionService)
else {
hideFixErrorWindow()
return
}
let state = store.withState { $0.fixErrorPanelState }
guard state.isPanelDisplayed,
let focusedEditor = state.focusedEditor,
let scrollViewRect = focusedEditor.element.parent?.rect
else {
hideFixErrorWindow()
return
}
let annotations = state.errorAnnotationsAtCursorPosition
guard !annotations.isEmpty,
let annotationRect = annotations.first(where: { $0.rect != nil})?.rect,
scrollViewRect.contains(annotationRect),
let screen = NSScreen.screens.first(where: { $0.frame.origin == .zero })
else {
hideFixErrorWindow()
return
}
var fixErrorPanelWindowFrame = windows.fixErrorPanelWindow.frame
fixErrorPanelWindowFrame.origin.x = annotationRect.minX - fixErrorPanelWindowFrame.width - Style.fixPanelToAnnotationSpacing
// Locate the window to the middle in Y
fixErrorPanelWindowFrame.origin.y = screen.frame.maxY - annotationRect.minY - annotationRect.height / 2 - fixErrorPanelWindowFrame.height / 2 + screen.frame.minY
windows.fixErrorPanelWindow.setFrame(fixErrorPanelWindowFrame, display: true, animate: false)
displayFixErrorWindow()
}
@MainActor
func handleFixErrorEditorNotification(notification: SourceEditor.AXNotification) async {
guard isFixErrorEnabled else {
hideFixErrorWindow()
return
}
switch notification.kind {
case .scrollPositionChanged:
store.send(.fixErrorPanel(.onScrollPositionChanged))
case .valueChanged:
store.send(.fixErrorPanel(.onEditorContentChanged))
case .selectedTextChanged:
store.send(.fixErrorPanel(.onCursorPositionChanged))
default:
break
}
}
}