import AppKitimport CodexBarCoreimport SwiftUI @MainActorstruct CopilotLoginFlow { static func run(settings: SettingsStore) async { let flow = CopilotDeviceFlow() do { let code = try await flow.requestDeviceCode() // Copy code to clipboard let pb = NSPasteboard.general pb.clearContents() pb.setString(code.userCode, forType: .string) let alert = NSAlert() alert.messageText = "GitHub Copilot Login" alert.informativeText = """ A device code has been copied to your clipboard: \(code.userCode) Please verify it at: \(code.verificationUri) """ alert.addButton(withTitle: "Open Browser") alert.addButton(withTitle: "Cancel") let response = alert.runModal() if response == .alertSecondButtonReturn { return // Cancelled } if let url = URL(string: code.verificationUri) { NSWorkspace.shared.open(url) } // Poll in background (modal blocks, but we need to wait for token effectively) // Ideally we'd show a "Waiting..." modal or spinner. // For simplicity, we can use a non-modal window or just block a Task? // `runModal` blocks the thread. We need to poll while the user is doing auth in browser. // But we already returned from runModal to open the browser. // We need a secondary "Waiting for confirmation..." alert or state. // Let's show a "Waiting" alert that can be cancelled. let waitingAlert = NSAlert() waitingAlert.messageText = "Waiting for Authentication..." waitingAlert.informativeText = """ Please complete the login in your browser. This window will close automatically when finished. """ waitingAlert.addButton(withTitle: "Cancel") let parentWindow = Self.resolveWaitingParentWindow() let hostWindow = parentWindow ?? Self.makeWaitingHostWindow() let shouldCloseHostWindow = parentWindow == nil let tokenTask = Task.detached(priority: .userInitiated) { try await flow.pollForToken(deviceCode: code.deviceCode, interval: code.interval) } let waitTask = Task { @MainActor in let response = await Self.presentWaitingAlert(waitingAlert, parentWindow: hostWindow) if response == .alertFirstButtonReturn { tokenTask.cancel() } return response } let tokenResult: Result<String, Error> do { let token = try await tokenTask.value tokenResult = .success(token) } catch { tokenResult = .failure(error) } Self.dismissWaitingAlert(waitingAlert, parentWindow: hostWindow, closeHost: shouldCloseHostWindow) let waitResponse = await waitTask.value if waitResponse == .alertFirstButtonReturn { return } switch tokenResult { case let .success(token): settings.copilotAPIToken = token settings.setProviderEnabled( provider: .copilot, metadata: ProviderRegistry.shared.metadata[.copilot]!, enabled: true) let success = NSAlert() success.messageText = "Login Successful" success.runModal() case let .failure(error): guard !(error is CancellationError) else { return } let err = NSAlert() err.messageText = "Login Failed" err.informativeText = error.localizedDescription err.runModal() } } catch { let err = NSAlert() err.messageText = "Login Failed" err.informativeText = error.localizedDescription err.runModal() } } @MainActor private static func presentWaitingAlert( _ alert: NSAlert, parentWindow: NSWindow) async -> NSApplication.ModalResponse { await withCheckedContinuation { continuation in alert.beginSheetModal(for: parentWindow) { response in continuation.resume(returning: response) } } } @MainActor private static func dismissWaitingAlert( _ alert: NSAlert, parentWindow: NSWindow, closeHost: Bool) { let alertWindow = alert.window if alertWindow.sheetParent != nil { parentWindow.endSheet(alertWindow) } else { alertWindow.orderOut(nil) } guard closeHost else { return } parentWindow.orderOut(nil) parentWindow.close() } @MainActor private static func resolveWaitingParentWindow() -> NSWindow? { if let window = NSApp.keyWindow ?? NSApp.mainWindow { return window } if let window = NSApp.windows.first(where: { $0.isVisible && !$0.ignoresMouseEvents }) { return window } return NSApp.windows.first } @MainActor private static func makeWaitingHostWindow() -> NSWindow { let window = NSWindow( contentRect: NSRect(x: 0, y: 0, width: 420, height: 1), styleMask: [.titled, .fullSizeContentView], backing: .buffered, defer: false) window.isReleasedWhenClosed = false window.titleVisibility = .hidden window.titlebarAppearsTransparent = true window.standardWindowButton(.closeButton)?.isHidden = true window.standardWindowButton(.miniaturizeButton)?.isHidden = true window.standardWindowButton(.zoomButton)?.isHidden = true window.backgroundColor = .clear window.isOpaque = false window.hasShadow = false window.level = .floating window.collectionBehavior = [.canJoinAllSpaces, .fullScreenAuxiliary] window.center() window.makeKeyAndOrderFront(nil) return window }}
import AppKit
import CodexBarCore
import SwiftUI
@MainActor
struct CopilotLoginFlow {
static func run(settings: SettingsStore) async {
let flow = CopilotDeviceFlow()
do {
let code = try await flow.requestDeviceCode()
// Copy code to clipboard
let pb = NSPasteboard.general
pb.clearContents()
pb.setString(code.userCode, forType: .string)
let alert = NSAlert()
alert.messageText = "GitHub Copilot Login"
alert.informativeText = """
A device code has been copied to your clipboard: \(code.userCode)
Please verify it at: \(code.verificationUri)
"""
alert.addButton(withTitle: "Open Browser")
alert.addButton(withTitle: "Cancel")
let response = alert.runModal()
if response == .alertSecondButtonReturn {
return // Cancelled
}
if let url = URL(string: code.verificationUri) {
NSWorkspace.shared.open(url)
}
// Poll in background (modal blocks, but we need to wait for token effectively)
// Ideally we'd show a "Waiting..." modal or spinner.
// For simplicity, we can use a non-modal window or just block a Task?
// `runModal` blocks the thread. We need to poll while the user is doing auth in browser.
// But we already returned from runModal to open the browser.
// We need a secondary "Waiting for confirmation..." alert or state.
// Let's show a "Waiting" alert that can be cancelled.
let waitingAlert = NSAlert()
waitingAlert.messageText = "Waiting for Authentication..."
waitingAlert.informativeText = """
Please complete the login in your browser.
This window will close automatically when finished.
"""
waitingAlert.addButton(withTitle: "Cancel")
let parentWindow = Self.resolveWaitingParentWindow()
let hostWindow = parentWindow ?? Self.makeWaitingHostWindow()
let shouldCloseHostWindow = parentWindow == nil
let tokenTask = Task.detached(priority: .userInitiated) {
try await flow.pollForToken(deviceCode: code.deviceCode, interval: code.interval)
}
let waitTask = Task { @MainActor in
let response = await Self.presentWaitingAlert(waitingAlert, parentWindow: hostWindow)
if response == .alertFirstButtonReturn {
tokenTask.cancel()
}
return response
}
let tokenResult: Result<String, Error>
do {
let token = try await tokenTask.value
tokenResult = .success(token)
} catch {
tokenResult = .failure(error)
}
Self.dismissWaitingAlert(waitingAlert, parentWindow: hostWindow, closeHost: shouldCloseHostWindow)
let waitResponse = await waitTask.value
if waitResponse == .alertFirstButtonReturn {
return
}
switch tokenResult {
case let .success(token):
settings.copilotAPIToken = token
settings.setProviderEnabled(
provider: .copilot,
metadata: ProviderRegistry.shared.metadata[.copilot]!,
enabled: true)
let success = NSAlert()
success.messageText = "Login Successful"
success.runModal()
case let .failure(error):
guard !(error is CancellationError) else { return }
let err = NSAlert()
err.messageText = "Login Failed"
err.informativeText = error.localizedDescription
err.runModal()
}
} catch {
let err = NSAlert()
err.messageText = "Login Failed"
err.informativeText = error.localizedDescription
err.runModal()
}
}
@MainActor
private static func presentWaitingAlert(
_ alert: NSAlert,
parentWindow: NSWindow) async -> NSApplication.ModalResponse
{
await withCheckedContinuation { continuation in
alert.beginSheetModal(for: parentWindow) { response in
continuation.resume(returning: response)
}
}
}
@MainActor
private static func dismissWaitingAlert(
_ alert: NSAlert,
parentWindow: NSWindow,
closeHost: Bool)
{
let alertWindow = alert.window
if alertWindow.sheetParent != nil {
parentWindow.endSheet(alertWindow)
} else {
alertWindow.orderOut(nil)
}
guard closeHost else { return }
parentWindow.orderOut(nil)
parentWindow.close()
}
@MainActor
private static func resolveWaitingParentWindow() -> NSWindow? {
if let window = NSApp.keyWindow ?? NSApp.mainWindow {
return window
}
if let window = NSApp.windows.first(where: { $0.isVisible && !$0.ignoresMouseEvents }) {
return window
}
return NSApp.windows.first
}
@MainActor
private static func makeWaitingHostWindow() -> NSWindow {
let window = NSWindow(
contentRect: NSRect(x: 0, y: 0, width: 420, height: 1),
styleMask: [.titled, .fullSizeContentView],
backing: .buffered,
defer: false)
window.isReleasedWhenClosed = false
window.titleVisibility = .hidden
window.titlebarAppearsTransparent = true
window.standardWindowButton(.closeButton)?.isHidden = true
window.standardWindowButton(.miniaturizeButton)?.isHidden = true
window.standardWindowButton(.zoomButton)?.isHidden = true
window.backgroundColor = .clear
window.isOpaque = false
window.hasShadow = false
window.level = .floating
window.collectionBehavior = [.canJoinAllSpaces, .fullScreenAuxiliary]
window.center()
window.makeKeyAndOrderFront(nil)
return window
}
}