import SwiftUI
import ParaSwift
import AuthenticationServices
struct SocialLoginView: View {
@EnvironmentObject var paraManager: ParaManager
@State private var navigationState: NavigationState = .idle
@Environment(\.webAuthenticationSession) private var webAuthenticationSession
@Environment(\.authorizationController) private var authorizationController
@State private var email = ""
@State private var error: Error?
@State private var showError = false
enum NavigationState {
case idle
case verification
case home
}
private func login(provider: OAuthProvider) {
Task {
do {
let email = try await paraManager.oAuthConnect(provider: provider, webAuthenticationSession: webAuthenticationSession)
await handleLogin(email: email)
} catch {
self.error = error
self.showError = true
}
}
}
private func handleLogin(email: String) async {
do {
self.email = email
let userExists = try await paraManager.checkIfUserExists(email: email)
if userExists {
try await paraManager.login(authorizationController: authorizationController, authInfo: EmailAuthInfo(email: email))
navigationState = .home
} else {
try await paraManager.createUser(email: email)
navigationState = .verification
}
} catch {
self.error = error
self.showError = true
}
}
var body: some View {
VStack {
Button {
login(provider: .google)
} label: {
HStack(spacing: 15) {
Image("google")
.resizable()
.frame(width: 24, height: 24)
Text("Login with Google")
.fontWeight(.semibold)
}
.frame(maxWidth: .infinity)
}
.buttonStyle(.borderedProminent)
.controlSize(.large)
.tint(.primary)
.foregroundStyle(.background)
Button {
login(provider: .discord)
} label: {
HStack(spacing: 15) {
Image("discord")
.resizable()
.frame(width: 24, height: 20)
Text("Login with Discord")
.fontWeight(.semibold)
}
.frame(maxWidth: .infinity)
}
.buttonStyle(.borderedProminent)
.controlSize(.large)
.tint(Color(uiColor: UIColor(rgb: 0x5865F2)))
Button {
login(provider: .apple)
} label: {
HStack(spacing: 15) {
Image("apple")
.resizable()
.frame(width: 24, height: 24)
Text("Login with Apple")
.fontWeight(.semibold)
}
.frame(maxWidth: .infinity)
}
.buttonStyle(.borderedProminent)
.controlSize(.large)
}
.alert("Connection Error", isPresented: $showError) {
Button("OK", role: .cancel) { }
} message: {
Text(error?.localizedDescription ?? "Unknown error occurred")
}
.navigationDestination(isPresented: Binding(
get: { navigationState == .verification },
set: { if !$0 { navigationState = .idle } }
)) {
VerifyEmailView(email: email)
}
.navigationDestination(isPresented: Binding(
get: { navigationState == .home },
set: { if !$0 { navigationState = .idle } }
)) {
HomeView()
}
.padding()
.navigationTitle("Social Login")
}
}
// Helper extension for UIColor from hex
extension UIColor {
convenience init(rgb: UInt) {
self.init(
red: CGFloat((rgb & 0xFF0000) >> 16) / 255.0,
green: CGFloat((rgb & 0x00FF00) >> 8) / 255.0,
blue: CGFloat(rgb & 0x0000FF) / 255.0,
alpha: CGFloat(1.0)
)
}
}