From f1df98e25334c59a09f7e609a969610b57358a5c Mon Sep 17 00:00:00 2001 From: kim-seonwoo Date: Wed, 9 Oct 2024 15:49:03 +0900 Subject: [PATCH] [Feat/#91] LoginViewModel Refactor --- .../Feature/LoginViewModel_Refactor.swift | 115 ++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 HMH_Tuist_iOS/Projects/Features/LoginFeature/Sources/Refactor_LoginFeature_Combine/Feature/LoginViewModel_Refactor.swift diff --git a/HMH_Tuist_iOS/Projects/Features/LoginFeature/Sources/Refactor_LoginFeature_Combine/Feature/LoginViewModel_Refactor.swift b/HMH_Tuist_iOS/Projects/Features/LoginFeature/Sources/Refactor_LoginFeature_Combine/Feature/LoginViewModel_Refactor.swift new file mode 100644 index 00000000..5385cf99 --- /dev/null +++ b/HMH_Tuist_iOS/Projects/Features/LoginFeature/Sources/Refactor_LoginFeature_Combine/Feature/LoginViewModel_Refactor.swift @@ -0,0 +1,115 @@ +// +// LoginViewModel_refactore.swift +// LoginFeatureInterface +// +// Created by Seonwoo Kim on 10/9/24. +// Copyright © 2024 HMH-iOS. All rights reserved. +// + +import Combine +import Core +import DSKit +import AuthenticationServices +import KakaoSDKUser + +class LoginViewModel_Refactor: NSObject, ObservableObject { + + private var useCase: LoginUseCaseType + private var cancelBag = CancelBag() + + @Published private(set) var state = State( + loginStatus: .loginFailure + ) + + init(useCase: LoginUseCaseType) { + self.useCase = useCase + } + + enum Action { + case kakaoLoginDidTap + case appleLoginDidTap + } + + struct State { + var loginStatus: LoginResponseType + } + + func send(action: Action) { + switch action { + case .kakaoLoginDidTap: + handleKakaoLogin() + case .appleLoginDidTap: + handleAppleLogin() + } + } + + private func handleKakaoLogin() { + if (UserApi.isKakaoTalkLoginAvailable()) { + UserApi.shared.loginWithKakaoTalk { [weak self] (oauthToken, error) in + if let error = error { + print("Kakao login error: \(error)") + return + } + if let oauthToken = oauthToken { + let idToken = oauthToken.accessToken + let token = "Bearer " + idToken + self?.requestLoginWithSocialToken(platform: "KAKAO", token: token) + } + } + } else { + UserApi.shared.loginWithKakaoAccount { [weak self] (oauthToken, error) in + if let error = error { + print("Kakao account login error: \(error)") + return + } + if let oauthToken = oauthToken { + let idToken = oauthToken.accessToken + let token = "Bearer " + idToken + self?.requestLoginWithSocialToken(platform: "KAKAO", token: token) + } + } + } + } + + private func handleAppleLogin() { + let request = ASAuthorizationAppleIDProvider().createRequest() + request.requestedScopes = [.fullName, .email] + + let authorizationController = ASAuthorizationController(authorizationRequests: [request]) + authorizationController.delegate = self + authorizationController.performRequests() + } + + private func requestLoginWithSocialToken(platform: String, token: String) { + useCase.requestLogin(platform: platform, socialToken: token) + .sink { _ in + } receiveValue: {_ in + bindLoginResponse() + }.store(in: cancelBag) + } + + private func bindLoginResponse() { + useCase.loginResponse + .sink(receiveCompletion: { _ in }, receiveValue: { [weak self] response in + self?.state.loginStatus = response + }).store(in: cancelBag) + } +} + +extension LoginViewModel_Refactor: ASAuthorizationControllerDelegate { + + func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) { + if let appleIDCredential = authorization.credential as? ASAuthorizationAppleIDCredential { + guard let identityToken = appleIDCredential.identityToken, + let idTokenString = String(data: identityToken, encoding: .utf8) else { + print("Failed to get Apple ID token") + return + } + requestLoginWithSocialToken(platform: "APPLE", token: idTokenString) + } + } + + func authorizationController(controller: ASAuthorizationController, didCompleteWithError error: Error) { + print("Apple login error: \(error.localizedDescription)") + } +}