Skip to content

Commit 93bc361

Browse files
committed
Merge branch 'feature/tweak-about-widget-location-update' into develop
2 parents d609ddb + 6b4e6f8 commit 93bc361

3 files changed

Lines changed: 35 additions & 40 deletions

File tree

Core/Sources/SuggestionWidget/FeatureReducers/PanelFeature.swift

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -96,12 +96,10 @@ public struct PanelFeature: ReducerProtocol {
9696

9797
case .switchToAnotherEditorAndUpdateContent:
9898
state.content.error = nil
99+
state.content.suggestion = nil
99100
return .run { send in
100101
guard let fileURL = xcodeInspector.realtimeActiveDocumentURL else { return }
101-
if let suggestion = await fetchSuggestionProvider(fileURL: fileURL) {
102-
await send(.presentSuggestionProvider(suggestion, displayContent: false))
103-
}
104-
102+
105103
await send(.sharedPanel(
106104
.promptToCodeGroup(
107105
.updateActivePromptToCode(documentURL: fileURL)

Core/Sources/SuggestionWidget/WidgetWindowsController.swift

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ actor WidgetWindowsController: NSObject {
2828
var updateWindowLocationTask: Task<Void, Error>?
2929
var lastUpdateWindowLocationTime = Date(timeIntervalSince1970: 0)
3030

31+
var beatingCompletionPanelTask: Task<Void, Error>?
32+
3133
deinit {
3234
userDefaultsObservers.presentationModeChangeObserver.onChange = {}
3335
observeToAppTask?.cancel()
@@ -61,15 +63,7 @@ actor WidgetWindowsController: NSObject {
6163

6264
xcodeInspector.$completionPanel.sink { [weak self] newValue in
6365
Task { [weak self] in
64-
if newValue == nil {
65-
// so that the buttons on the suggestion panel could be
66-
// clicked
67-
// before the completion panel updates the location of the
68-
// suggestion panel
69-
try await Task.sleep(nanoseconds: 400_000_000)
70-
}
71-
await self?.updateWindowLocation(animated: false, immediately: false)
72-
await self?.updateWindowOpacity(immediately: false)
66+
await self?.handleCompletionPanelChange(isDisplaying: newValue != nil)
7367
}
7468
}.store(in: &cancellable)
7569

@@ -299,10 +293,10 @@ private extension WidgetWindowsController {
299293
await send(.updateFocusingDocumentURL)
300294
}
301295

302-
func updateWidgetsAndNotifyChangeOfEditor() async {
303-
await updateWindowLocation(animated: false, immediately: false)
304-
await updateWindowOpacity(immediately: false)
296+
func updateWidgetsAndNotifyChangeOfEditor(immediately: Bool) async {
305297
await send(.panel(.switchToAnotherEditorAndUpdateContent))
298+
await updateWindowLocation(animated: false, immediately: immediately)
299+
await updateWindowOpacity(immediately: immediately)
306300
}
307301

308302
func updateWidgets() async {
@@ -313,9 +307,11 @@ private extension WidgetWindowsController {
313307
switch notification.kind {
314308
case .focusedWindowChanged, .focusedUIElementChanged:
315309
await hideWidgetForTransitions()
316-
await updateWidgetsAndNotifyChangeOfEditor()
317-
case .applicationActivated, .mainWindowChanged:
318-
await updateWidgetsAndNotifyChangeOfEditor()
310+
await updateWidgetsAndNotifyChangeOfEditor(immediately: true)
311+
case .applicationActivated:
312+
await updateWidgetsAndNotifyChangeOfEditor(immediately: false)
313+
case .mainWindowChanged:
314+
await updateWidgetsAndNotifyChangeOfEditor(immediately: false)
319315
case .applicationDeactivated,
320316
.moved,
321317
.resized,
@@ -371,6 +367,22 @@ private extension WidgetWindowsController {
371367
}
372368
}
373369
}
370+
371+
func handleCompletionPanelChange(isDisplaying: Bool) {
372+
beatingCompletionPanelTask?.cancel()
373+
beatingCompletionPanelTask = Task {
374+
if !isDisplaying {
375+
// so that the buttons on the suggestion panel could be
376+
// clicked
377+
// before the completion panel updates the location of the
378+
// suggestion panel
379+
try await Task.sleep(nanoseconds: 400_000_000)
380+
}
381+
382+
await updateWindowLocation(animated: false, immediately: false)
383+
await updateWindowOpacity(immediately: false)
384+
}
385+
}
374386
}
375387

376388
extension WidgetWindowsController {

Tool/Sources/AsyncPassthroughSubject/AsyncPassthroughSubject.swift

Lines changed: 6 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,19 @@
11
import AppKit
22
import Foundation
33

4-
/// It uses notification center to mimic the behavior of a passthrough subject.
54
public actor AsyncPassthroughSubject<Element> {
6-
let name: Notification.Name
75
var tasks: [AsyncStream<Element>.Continuation] = []
86

97
deinit {
108
tasks.forEach { $0.finish() }
119
}
1210

13-
public init() {
14-
name = NSNotification.Name(
15-
"AsyncPassthroughSubject-\(UUID().uuidString)-\(String(describing: Element.self))"
16-
)
17-
}
11+
public init() {}
1812

1913
public func notifications() -> AsyncStream<Element> {
20-
AsyncStream { [weak self, name] continuation in
14+
AsyncStream { [weak self] continuation in
2115
let task = Task { [weak self] in
2216
await self?.storeContinuation(continuation)
23-
let notifications = NotificationCenter.default.notifications(named: name)
24-
.compactMap {
25-
$0.object as? Element
26-
}
27-
for await notification in notifications {
28-
try Task.checkCancellation()
29-
guard self != nil else {
30-
continuation.finish()
31-
return
32-
}
33-
continuation.yield(notification)
34-
}
3517
}
3618

3719
continuation.onTermination = { termination in
@@ -46,7 +28,10 @@ public actor AsyncPassthroughSubject<Element> {
4628
}
4729

4830
func _send(_ element: Element) {
49-
NotificationCenter.default.post(name: name, object: element)
31+
let tasks = tasks
32+
for task in tasks {
33+
task.yield(element)
34+
}
5035
}
5136

5237
func storeContinuation(_ continuation: AsyncStream<Element>.Continuation) {

0 commit comments

Comments
 (0)