import AppKit extension WidgetWindowsController { func setupNESSuggestionPanelObservers() { Task { @MainActor in let nesContentPublisher = store.publisher .map(\.panelState.nesSuggestionPanelState.nesContent) .removeDuplicates() .sink { [weak self] _ in Task { [weak self] in await self?.updateWindowLocation(animated: false, immediately: true) } } await self.storeCancellables([nesContentPublisher]) } } @MainActor func hideNESDiffWindow() { NSAnimationContext.runAnimationGroup { context in context.duration = 0.2 windows.nesDiffWindow.animator().alphaValue = 0 windows.nesDiffWindow.setIsVisible(false) } } @MainActor func updateNESDiffWindowFrame( _ location: WidgetLocation.NESPanelLocation, animated: Bool, trigger: WidgetLocation.LocationTrigger ) async { windows.nesDiffWindow.layoutIfNeeded() guard let contentView = windows.nesDiffWindow.contentView else { return } let effectiveSize: NSSize? = { let fittingSize = contentView.fittingSize if fittingSize.width > 0 && fittingSize.height > 0 { return fittingSize } let intrinsicSize = contentView.intrinsicContentSize if intrinsicSize.width > 0 && intrinsicSize.height > 0 { return intrinsicSize } return nil }() guard let contentSize = effectiveSize, contentSize.width.isFinite, contentSize.height.isFinite, let frame = location.calcDiffViewFrame(contentSize: contentSize) else { return } windows.nesDiffWindow.setFrame( frame, display: false, animate: animated ) } @MainActor func updateNESNotificationWindowFrame( _ location: WidgetLocation.NESPanelLocation, animated: Bool ) async { var notificationWindowFrame = windows.nesNotificationWindow.frame let scrollViewFrame = location.scrollViewFrame let screenFrame = location.screenFrame notificationWindowFrame.origin.x = scrollViewFrame.minX + scrollViewFrame.width / 2 - notificationWindowFrame.width / 2 notificationWindowFrame.origin.y = screenFrame.height - scrollViewFrame.maxY + Style.nesSuggestionMenuLeadingPadding * 2 windows.nesNotificationWindow.setFrame( notificationWindowFrame, display: false, animate: animated ) } }