@@ -53,6 +53,11 @@ final class WidgetWindowsController: NSObject {
5353 guard let app else { return }
5454 Task { [ weak self] in await self ? . activate ( app) }
5555 } . store ( in: & cancellable)
56+
57+ xcodeInspector. $focusedEditor. sink { [ weak self] editor in
58+ guard let editor else { return }
59+ Task { [ weak self] in await self ? . observe ( to: editor) }
60+ } . store ( in: & cancellable)
5661
5762 xcodeInspector. $completionPanel. sink { [ weak self] newValue in
5863 Task { [ weak self] in
@@ -160,11 +165,10 @@ final class WidgetWindowsController: NSObject {
160165 function: StaticString = #function,
161166 line: UInt = #line
162167 ) async {
163- let state = store. withState { $0 }
164- let isChatPanelDetached = state. chatPanelState. chatPanelInASeparateWindow
165-
166168 @Sendable @MainActor
167169 func update( ) async {
170+ let state = store. withState { $0 }
171+ let isChatPanelDetached = state. chatPanelState. chatPanelInASeparateWindow
168172 guard let widgetLocation = generateWidgetLocation ( ) else { return }
169173 await updatePanelState ( widgetLocation)
170174
@@ -275,34 +279,24 @@ private extension WidgetWindowsController {
275279 }
276280
277281 func observe( to app: AppInstanceInspector ) async {
282+ Task {
283+ await updateWindowLocation ( animated: false , immediately: true )
284+ await updateWindowOpacity ( immediately: true )
285+ }
278286 guard let app = app as? XcodeAppInstanceInspector else {
279- Task {
280- await updateWindowLocation ( animated: false , immediately: true )
281- await updateWindowOpacity ( immediately: true )
282- }
283287 return
284288 }
285289 let notifications = app. axNotifications
286- if let focusedEditor = xcodeInspector. focusedEditor {
287- await observe ( to: focusedEditor)
288- }
289-
290290 let task = Task {
291291 await windows. orderFront ( )
292292
293293 let documentURL = await MainActor . run { store. withState { $0. focusingDocumentURL } }
294294 for await notification in notifications {
295- if [ . uiElementDestroyed, . created, . xcodeCompletionPanelChanged]
296- . contains ( notification. kind) { continue }
297-
298295 try Task . checkCancellation ( )
299296
300- // Hide the widgets before switching to another window/editor
301- // so the transition looks better.
302- if [
303- . focusedUIElementChanged,
304- . focusedWindowChanged,
305- ] . contains ( notification. kind) {
297+ /// Hide the widgets before switching to another window/editor
298+ /// so the transition looks better.
299+ func hideWidgetForTransitions( ) async {
306300 let newDocumentURL = xcodeInspector. realtimeActiveDocumentURL
307301 if documentURL != newDocumentURL {
308302 await send ( . panel( . removeDisplayedContent) )
@@ -311,23 +305,34 @@ private extension WidgetWindowsController {
311305 await send ( . updateFocusingDocumentURL)
312306 }
313307
314- // update widgets.
315- if [
316- . focusedUIElementChanged,
317- . applicationActivated,
318- . mainWindowChanged,
319- . focusedWindowChanged,
320- ] . contains ( notification. kind) {
308+ func updateWidgetsAndNotifyChangeOfEditor( ) async {
321309 await updateWindowLocation ( animated: false , immediately: false )
322310 await updateWindowOpacity ( immediately: false )
323- if let editor = xcodeInspector. focusedEditor {
324- await observe ( to: editor)
325- }
326311 await send ( . panel( . switchToAnotherEditorAndUpdateContent) )
327- } else {
312+ }
313+
314+ func updateWidgets( ) async {
328315 await updateWindowLocation ( animated: false , immediately: false )
329316 await updateWindowOpacity ( immediately: false )
330317 }
318+
319+ switch notification. kind {
320+ case . focusedWindowChanged, . focusedUIElementChanged:
321+ await hideWidgetForTransitions ( )
322+ await updateWidgetsAndNotifyChangeOfEditor ( )
323+ case . applicationActivated, . mainWindowChanged:
324+ await updateWidgetsAndNotifyChangeOfEditor ( )
325+ case . applicationDeactivated,
326+ . moved,
327+ . resized,
328+ . windowMoved,
329+ . windowResized,
330+ . windowMiniaturized,
331+ . windowDeminiaturized:
332+ await updateWidgets ( )
333+ case . created, . uiElementDestroyed, . xcodeCompletionPanelChanged:
334+ continue
335+ }
331336 }
332337 }
333338
@@ -343,19 +348,31 @@ private extension WidgetWindowsController {
343348 . filter { $0. kind == . scrollPositionChanged }
344349
345350 if #available( macOS 13 . 0 , * ) {
346- for await _ in merge (
351+ for await notification in merge (
347352 selectionRangeChange. debounce ( for: Duration . milliseconds ( 500 ) ) ,
348353 scroll
349354 ) {
350355 guard xcodeInspector. latestActiveXcode != nil else { return }
351356 try Task . checkCancellation ( )
357+
358+ // for better looking
359+ if notification. kind == . scrollPositionChanged {
360+ await hideSuggestionPanelWindow ( )
361+ }
362+
352363 await updateWindowLocation ( animated: false , immediately: false )
353364 await updateWindowOpacity ( immediately: false )
354365 }
355366 } else {
356- for await _ in merge ( selectionRangeChange, scroll) {
367+ for await notification in merge ( selectionRangeChange, scroll) {
357368 guard xcodeInspector. latestActiveXcode != nil else { return }
358369 try Task . checkCancellation ( )
370+
371+ // for better looking
372+ if notification. kind == . scrollPositionChanged {
373+ await hideSuggestionPanelWindow ( )
374+ }
375+
359376 await updateWindowLocation ( animated: false , immediately: false )
360377 await updateWindowOpacity ( immediately: false )
361378 }
@@ -373,6 +390,11 @@ extension WidgetWindowsController {
373390 windows. sharedPanelWindow. alphaValue = 0
374391 windows. suggestionPanelWindow. alphaValue = 0
375392 }
393+
394+ @MainActor
395+ func hideSuggestionPanelWindow( ) {
396+ windows. suggestionPanelWindow. alphaValue = 0
397+ }
376398
377399 func generateWidgetLocation( ) -> WidgetLocation ? {
378400 if let application = xcodeInspector. latestActiveXcode? . appElement {
0 commit comments