wake-ios/wake/View/Components/AppleSignInButton.swift
2025-08-22 18:58:08 +08:00

95 lines
3.1 KiB
Swift

import SwiftUI
import AuthenticationServices
import CryptoKit
/// Apple
struct AppleSignInButton: View {
// MARK: -
///
let onRequest: (ASAuthorizationAppleIDRequest) -> Void
///
let onCompletion: (Result<ASAuthorization, Error>) -> Void
///
let buttonText: String
// MARK: -
init(buttonText: String = "Continue with Apple",
onRequest: @escaping (ASAuthorizationAppleIDRequest) -> Void,
onCompletion: @escaping (Result<ASAuthorization, Error>) -> Void) {
self.buttonText = buttonText
self.onRequest = onRequest
self.onCompletion = onCompletion
}
// MARK: -
var body: some View {
Button(action: handleSignIn) {
HStack(alignment: .center, spacing: 8) {
Image(systemName: "applelogo")
.font(.system(size: 20, weight: .regular))
Text(buttonText)
.font(.system(size: 18, weight: .regular))
}
.frame(maxWidth: .infinity)
.frame(height: 60)
.background(Color.white)
.foregroundColor(.black)
.cornerRadius(30)
.overlay(
RoundedRectangle(cornerRadius: 30)
.stroke(Color.black, lineWidth: 1) // 使
)
}
}
// MARK: -
private func handleSignIn() {
let provider = ASAuthorizationAppleIDProvider()
let request = provider.createRequest()
request.requestedScopes = [.fullName, .email]
// nonce
let nonce = String.randomURLSafeString(length: 32)
request.nonce = sha256(nonce)
//
onRequest(request)
//
let controller = ASAuthorizationController(authorizationRequests: [request])
controller.delegate = Coordinator(onCompletion: onCompletion)
controller.performRequests()
}
private func sha256(_ input: String) -> String {
let inputData = Data(input.utf8)
let hashedData = SHA256.hash(data: inputData)
return hashedData.compactMap { String(format: "%02x", $0) }.joined()
}
// MARK: -
private class Coordinator: NSObject, ASAuthorizationControllerDelegate {
let onCompletion: (Result<ASAuthorization, Error>) -> Void
init(onCompletion: @escaping (Result<ASAuthorization, Error>) -> Void) {
self.onCompletion = onCompletion
}
//
func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) {
onCompletion(.success(authorization))
}
//
func authorizationController(controller: ASAuthorizationController, didCompleteWithError error: Error) {
onCompletion(.failure(error))
}
}
}