import AppKit import SwiftUI struct OAuthSetupView: View { @State private var tokenManager = TokenManager.shared @State private var statusMessage: String? var body: some View { VStack(spacing: 16) { Image(systemName: "link.circle") .font(.system(size: 40)) .foregroundStyle(.blue) Text("Connect Feishu") .font(.headline) Text("Authorize Bugger to read bugs assigned to you from your Feishu Bitable.") .font(.caption) .foregroundStyle(.secondary) .multilineTextAlignment(.center) if tokenManager.authorizeURL == nil { Text("Set FEISHU_APP_ID and FEISHU_APP_SECRET in the Xcode build settings before connecting.") .font(.caption) .foregroundStyle(.orange) .multilineTextAlignment(.center) } else { Button("Connect Feishu") { connectFeishu() } .buttonStyle(.borderedProminent) } if case .authenticating = tokenManager.state { ProgressView("Completing sign-in...") } if case .error(let message) = tokenManager.state { Text(message) .font(.caption) .foregroundStyle(.red) .multilineTextAlignment(.center) } if let statusMessage { Text(statusMessage) .font(.caption) .foregroundStyle(.secondary) } } .padding(24) .frame(maxWidth: .infinity, maxHeight: .infinity) } private func connectFeishu() { Task { let server = LocalOAuthServer() tokenManager.authService.redirectURI = server.redirectURI guard let url = tokenManager.authorizeURL else { statusMessage = "Missing credentials. Check FEISHU_APP_ID." return } statusMessage = "Complete authorization in your browser." NSWorkspace.shared.open(url) do { let code = try await server.receiveCode() statusMessage = "Completing sign-in..." try await tokenManager.handleCallback(code: code) await PollerService.shared.startIfConfigured() await PollerService.shared.fetchNow() } catch { await MainActor.run { tokenManager.setError(error.localizedDescription) } } } } }