95 lines
3.3 KiB
Swift
95 lines
3.3 KiB
Swift
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 case .authenticating = tokenManager.state {
|
|
ProgressView("Completing sign-in...")
|
|
} else 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)
|
|
.disabled(statusMessage != nil)
|
|
}
|
|
|
|
if case .error(let message) = tokenManager.state {
|
|
VStack(spacing: 4) {
|
|
Text("Authorization failed")
|
|
.font(.caption)
|
|
.fontWeight(.medium)
|
|
.foregroundStyle(.red)
|
|
Text(message)
|
|
.font(.caption2)
|
|
.foregroundStyle(.secondary)
|
|
.multilineTextAlignment(.center)
|
|
Button("Try again") {
|
|
tokenManager.clearTokens()
|
|
statusMessage = nil
|
|
}
|
|
.font(.caption)
|
|
}
|
|
}
|
|
|
|
if let statusMessage, !statusMessage.isEmpty,
|
|
tokenManager.state != .authenticating {
|
|
Text(statusMessage)
|
|
.font(.caption)
|
|
.foregroundStyle(.secondary)
|
|
}
|
|
}
|
|
.padding(24)
|
|
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
|
}
|
|
|
|
private func connectFeishu() {
|
|
statusMessage = "Starting..."
|
|
Task {
|
|
let server = LocalOAuthServer(port: 18_923)
|
|
tokenManager.authService.redirectURI = server.redirectURI
|
|
|
|
guard let url = tokenManager.authorizeURL else {
|
|
statusMessage = nil
|
|
tokenManager.setError("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)
|
|
statusMessage = nil
|
|
await PollerService.shared.startIfConfigured()
|
|
await PollerService.shared.fetchNow()
|
|
} catch {
|
|
statusMessage = nil
|
|
tokenManager.setError(error.localizedDescription)
|
|
}
|
|
}
|
|
}
|
|
}
|