Files
claudechecker/ClaudeChecker/LoginView.swift
T

83 lines
2.6 KiB
Swift

import SwiftUI
import WebKit
// MARK: - Login Web View
struct LoginWebView: NSViewRepresentable {
let onAuthenticated: () -> Void
func makeNSView(context: Context) -> WKWebView {
let config = WKWebViewConfiguration()
config.websiteDataStore = WKWebsiteDataStore.default()
let webView = WKWebView(frame: .zero, configuration: config)
webView.navigationDelegate = context.coordinator
webView.load(URLRequest(url: URL(string: "https://claude.ai/login")!))
return webView
}
func updateNSView(_ nsView: WKWebView, context: Context) {}
func makeCoordinator() -> Coordinator {
Coordinator(onAuthenticated: onAuthenticated)
}
class Coordinator: NSObject, WKNavigationDelegate {
let onAuthenticated: () -> Void
init(onAuthenticated: @escaping () -> Void) {
self.onAuthenticated = onAuthenticated
}
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
WKWebsiteDataStore.default().httpCookieStore.getAllCookies { cookies in
let hasSession = cookies.contains {
$0.domain.contains("claude.ai") &&
($0.name == "sessionKey" || $0.name == "__Secure-next-auth.session-token")
}
if hasSession {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
self.onAuthenticated()
}
}
}
}
}
}
// MARK: - Login Sheet View
struct LoginSheetView: View {
@Binding var isPresented: Bool
let onDone: () -> Void
@State private var authenticated = false
var body: some View {
VStack(spacing: 0) {
HStack {
Text(authenticated ? "✓ Signed in — loading data…" : "Sign in to Claude")
.font(.system(size: 13, weight: .semibold))
Spacer()
Button("Cancel") { isPresented = false }
.buttonStyle(.bordered)
.controlSize(.small)
}
.padding(.horizontal, 14)
.padding(.vertical, 10)
.background(Color(nsColor: .windowBackgroundColor))
Divider()
LoginWebView {
authenticated = true
// Auto-dismiss and refresh after brief delay
DispatchQueue.main.asyncAfter(deadline: .now() + 0.8) {
isPresented = false
onDone()
}
}
}
.frame(width: 460, height: 560)
}
}