@@ -32,25 +32,20 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate {
3232 let service = Service . shared
3333 var statusBarItem : NSStatusItem !
3434 var statusMenuItem : NSMenuItem !
35+ var authMenuItem : NSMenuItem !
3536 var xpcController : XPCController ?
3637 let updateChecker =
3738 UpdateChecker (
3839 hostBundle: Bundle ( url: locateHostBundleURL ( url: Bundle . main. bundleURL) ) ,
3940 checkerDelegate: ExtensionUpdateCheckerDelegate ( )
4041 )
41- let statusChecker : AuthStatusChecker = AuthStatusChecker ( )
4242 var xpcExtensionService : XPCExtensionService ?
4343 private var cancellables = Set < AnyCancellable > ( )
4444 private var progressView : NSProgressIndicator ?
45- private var idleIcon = NSImage ( named: " MenuBarIcon " )
4645
4746 func applicationDidFinishLaunching( _: Notification ) {
4847 if ProcessInfo . processInfo. environment [ " IS_UNIT_TEST " ] == " YES " { return }
4948 _ = XcodeInspector . shared
50- service. markAsProcessing = { [ weak self] in
51- guard let self = self else { return }
52- self . markAsProcessing ( $0)
53- }
5449 service. start ( )
5550 AXIsProcessTrustedWithOptions ( [
5651 kAXTrustedCheckOptionPrompt. takeRetainedValue ( ) as NSString : true ,
@@ -63,7 +58,8 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate {
6358 buildStatusBarMenu ( )
6459 watchServiceStatus ( )
6560 watchAXStatus ( )
66- updateStatusBarItem ( ) // set the initial status
61+ watchAuthStatus ( )
62+ setInitialStatusBarStatus ( )
6763 }
6864
6965 @objc func quit( ) {
@@ -183,16 +179,44 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate {
183179 }
184180 }
185181
182+ func watchAuthStatus( ) {
183+ let notifications = DistributedNotificationCenter . default ( ) . notifications ( named: . authStatusDidChange)
184+ Task { [ weak self] in
185+ for await _ in notifications {
186+ guard let self else { return }
187+ await self . forceAuthStatusCheck ( )
188+ }
189+ }
190+ }
191+
192+ func setInitialStatusBarStatus( ) {
193+ Task {
194+ let authStatus = await Status . shared. getAuthStatus ( )
195+ if authStatus == . unknown {
196+ // temporarily kick off a language server instance to prime the initial auth status
197+ await forceAuthStatusCheck ( )
198+ }
199+ updateStatusBarItem ( )
200+ }
201+ }
202+
203+ func forceAuthStatusCheck( ) async {
204+ do {
205+ let service = try GitHubCopilotService ( )
206+ _ = try await service. checkStatus ( )
207+ try await service. shutdown ( )
208+ try await service. exit ( )
209+ } catch {
210+ Logger . service. error ( " Failed to read auth status: \( error) " )
211+ }
212+ }
213+
186214 func updateStatusBarItem( ) {
187215 Task { @MainActor in
188216 let status = await Status . shared. getStatus ( )
189- let image = if status. system {
190- NSImage ( systemSymbolName: status. icon, accessibilityDescription: nil )
191- } else {
192- NSImage ( named: status. icon)
193- }
194- idleIcon = image
217+ let image = status. icon. nsImage
195218 self . statusBarItem. button? . image = image
219+ self . authMenuItem. title = status. authMessage
196220 if let message = status. message {
197221 // TODO switch to attributedTitle to enable line breaks and color.
198222 self . statusMenuItem. title = message
@@ -201,6 +225,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate {
201225 } else {
202226 self . statusMenuItem. isHidden = true
203227 }
228+ self . markAsProcessing ( status. inProgress)
204229 }
205230 }
206231
@@ -209,7 +234,6 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate {
209234 // No longer in progress
210235 progressView? . removeFromSuperview ( )
211236 progressView = nil
212- statusBarItem. button? . image = idleIcon
213237 return
214238 }
215239 if progressView != nil {
0 commit comments