convert more combine publishers to async
This commit is contained in:
@ -5,7 +5,7 @@ import SwiftUI
|
||||
import Utils
|
||||
import Views
|
||||
|
||||
final class CreateProfileViewModel: ObservableObject {
|
||||
@MainActor final class CreateProfileViewModel: ObservableObject {
|
||||
private(set) var initialUserProfile = UserProfile(username: "", name: "", bio: nil)
|
||||
var isConfigured = false
|
||||
|
||||
@ -39,7 +39,9 @@ final class CreateProfileViewModel: ObservableObject {
|
||||
|
||||
switch profileOrError {
|
||||
case let .left(userProfile):
|
||||
submitProfile(userProfile: userProfile, authenticator: authenticator)
|
||||
Task {
|
||||
await submitProfile(userProfile: userProfile, authenticator: authenticator)
|
||||
}
|
||||
case let .right(errorMessage):
|
||||
validationErrorMessage = errorMessage
|
||||
}
|
||||
@ -76,16 +78,14 @@ final class CreateProfileViewModel: ObservableObject {
|
||||
.store(in: &subscriptions)
|
||||
}
|
||||
|
||||
func submitProfile(userProfile: UserProfile, authenticator: Authenticator) {
|
||||
authenticator
|
||||
.createAccount(userProfile: userProfile).sink(
|
||||
receiveCompletion: { [weak self] completion in
|
||||
guard case let .failure(loginError) = completion else { return }
|
||||
self?.loginError = loginError
|
||||
},
|
||||
receiveValue: { _ in }
|
||||
)
|
||||
.store(in: &subscriptions)
|
||||
func submitProfile(userProfile: UserProfile, authenticator: Authenticator) async {
|
||||
do {
|
||||
try await authenticator.createAccount(userProfile: userProfile)
|
||||
} catch {
|
||||
if let error = error as? LoginError {
|
||||
loginError = error
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func configure(profile: UserProfile, dataService: DataService) {
|
||||
|
||||
@ -5,23 +5,21 @@ import SwiftUI
|
||||
import Utils
|
||||
import Views
|
||||
|
||||
final class NewAppleSignupViewModel: ObservableObject {
|
||||
@MainActor final class NewAppleSignupViewModel: ObservableObject {
|
||||
@Published var loginError: LoginError?
|
||||
|
||||
var subscriptions = Set<AnyCancellable>()
|
||||
|
||||
init() {}
|
||||
|
||||
func submitProfile(userProfile: UserProfile, authenticator: Authenticator) {
|
||||
authenticator
|
||||
.createAccount(userProfile: userProfile).sink(
|
||||
receiveCompletion: { [weak self] completion in
|
||||
guard case let .failure(loginError) = completion else { return }
|
||||
self?.loginError = loginError
|
||||
},
|
||||
receiveValue: { _ in }
|
||||
)
|
||||
.store(in: &subscriptions)
|
||||
func submitProfile(userProfile: UserProfile, authenticator: Authenticator) async {
|
||||
do {
|
||||
try await authenticator.createAccount(userProfile: userProfile)
|
||||
} catch {
|
||||
if let error = error as? LoginError {
|
||||
loginError = error
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -48,7 +46,11 @@ struct NewAppleSignupView: View {
|
||||
|
||||
VStack {
|
||||
Button(
|
||||
action: { viewModel.submitProfile(userProfile: userProfile, authenticator: authenticator) },
|
||||
action: {
|
||||
Task {
|
||||
await viewModel.submitProfile(userProfile: userProfile, authenticator: authenticator)
|
||||
}
|
||||
},
|
||||
label: { Text("Continue") }
|
||||
)
|
||||
.buttonStyle(SolidCapsuleButtonStyle(color: .appDeepBackground, width: 300))
|
||||
|
||||
@ -1,12 +1,11 @@
|
||||
import AuthenticationServices
|
||||
import Combine
|
||||
import Models
|
||||
import Services
|
||||
import SwiftUI
|
||||
import Utils
|
||||
import Views
|
||||
|
||||
final class RegistrationViewModel: ObservableObject {
|
||||
@MainActor final class RegistrationViewModel: ObservableObject {
|
||||
enum RegistrationState {
|
||||
case createProfile(userProfile: UserProfile)
|
||||
case newAppleSignUp(userProfile: UserProfile)
|
||||
@ -15,12 +14,10 @@ final class RegistrationViewModel: ObservableObject {
|
||||
@Published var loginError: LoginError?
|
||||
@Published var registrationState: RegistrationState?
|
||||
|
||||
var subscriptions = Set<AnyCancellable>()
|
||||
|
||||
func handleAppleSignInCompletion(result: Result<ASAuthorization, Error>, authenticator: Authenticator) {
|
||||
switch AppleSigninPayload.parse(authResult: result) {
|
||||
case let .success(payload):
|
||||
handleAppleToken(payload: payload, authenticator: authenticator)
|
||||
Task { await handleAppleToken(payload: payload, authenticator: authenticator) }
|
||||
case let .failure(error):
|
||||
switch error {
|
||||
case .unauthorized, .unknown:
|
||||
@ -31,39 +28,34 @@ final class RegistrationViewModel: ObservableObject {
|
||||
}
|
||||
}
|
||||
|
||||
private func handleAppleToken(payload: AppleSigninPayload, authenticator: Authenticator) {
|
||||
authenticator.submitAppleToken(token: payload.token).sink(
|
||||
receiveCompletion: { [weak self] completion in
|
||||
guard case let .failure(loginError) = completion else { return }
|
||||
switch loginError {
|
||||
case .unauthorized, .unknown:
|
||||
self?.handleAppleSignUp(authenticator: authenticator, payload: payload)
|
||||
case .network:
|
||||
self?.loginError = loginError
|
||||
}
|
||||
},
|
||||
receiveValue: { _ in }
|
||||
)
|
||||
.store(in: &subscriptions)
|
||||
private func handleAppleToken(payload: AppleSigninPayload, authenticator: Authenticator) async {
|
||||
do {
|
||||
try await authenticator.submitAppleToken(token: payload.token)
|
||||
} catch {
|
||||
let submitTokenError = (error as? LoginError) ?? .unknown
|
||||
switch submitTokenError {
|
||||
case .unauthorized, .unknown:
|
||||
await handleAppleSignUp(authenticator: authenticator, payload: payload)
|
||||
case .network:
|
||||
loginError = submitTokenError
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func handleAppleSignUp(authenticator: Authenticator, payload: AppleSigninPayload) {
|
||||
authenticator
|
||||
.createPendingAccountUsingApple(token: payload.token, name: payload.fullName)
|
||||
.sink(
|
||||
receiveCompletion: { [weak self] completion in
|
||||
guard case let .failure(loginError) = completion else { return }
|
||||
self?.loginError = loginError
|
||||
},
|
||||
receiveValue: { [weak self] userProfile in
|
||||
if userProfile.name.isEmpty {
|
||||
self?.registrationState = .createProfile(userProfile: userProfile)
|
||||
} else {
|
||||
self?.registrationState = .newAppleSignUp(userProfile: userProfile)
|
||||
}
|
||||
}
|
||||
private func handleAppleSignUp(authenticator: Authenticator, payload: AppleSigninPayload) async {
|
||||
do {
|
||||
let pendingUserProfile = try await authenticator.createPendingAccountUsingApple(
|
||||
token: payload.token,
|
||||
name: payload.fullName
|
||||
)
|
||||
.store(in: &subscriptions)
|
||||
if pendingUserProfile.name.isEmpty {
|
||||
registrationState = .createProfile(userProfile: pendingUserProfile)
|
||||
} else {
|
||||
registrationState = .newAppleSignUp(userProfile: pendingUserProfile)
|
||||
}
|
||||
} catch {
|
||||
loginError = (error as? LoginError) ?? .unknown
|
||||
}
|
||||
}
|
||||
|
||||
func handleGoogleAuth(authenticator: Authenticator) async {
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
import Combine
|
||||
import Foundation
|
||||
import Models
|
||||
|
||||
@ -6,12 +5,12 @@ public extension Authenticator {
|
||||
func createPendingAccountUsingApple(
|
||||
token: String,
|
||||
name: PersonNameComponents?
|
||||
) -> AnyPublisher<UserProfile, LoginError> {
|
||||
) async throws -> UserProfile {
|
||||
let params = CreatePendingAccountParams(token: token, provider: .apple, fullName: name)
|
||||
return createPendingAccount(params: params)
|
||||
return try await createPendingAccount(params: params)
|
||||
}
|
||||
|
||||
func createAccount(userProfile: UserProfile) -> AnyPublisher<Void, LoginError> {
|
||||
func createAccount(userProfile: UserProfile) async throws {
|
||||
let params = CreateAccountParams(
|
||||
pendingUserToken: pendingUserToken ?? "",
|
||||
userProfile: userProfile
|
||||
@ -19,36 +18,29 @@ public extension Authenticator {
|
||||
|
||||
let encodedParams = (try? JSONEncoder().encode(params)) ?? Data()
|
||||
|
||||
return networker
|
||||
.createAccount(params: encodedParams)
|
||||
.tryMap { [weak self] in
|
||||
try ValetKey.authCookieString.setValue($0.commentedAuthCookieString)
|
||||
try ValetKey.authToken.setValue($0.authToken)
|
||||
self?.pendingUserToken = nil
|
||||
self?.isLoggedIn = true
|
||||
do {
|
||||
let authPayload = try await networker.createAccount(params: encodedParams)
|
||||
try ValetKey.authCookieString.setValue(authPayload.commentedAuthCookieString)
|
||||
try ValetKey.authToken.setValue(authPayload.authToken)
|
||||
DispatchQueue.main.async {
|
||||
self.pendingUserToken = nil
|
||||
self.isLoggedIn = true
|
||||
}
|
||||
.mapError { error in
|
||||
let serverError = (error as? ServerError) ?? ServerError.unknown
|
||||
return LoginError.make(serverError: serverError)
|
||||
}
|
||||
.eraseToAnyPublisher()
|
||||
} catch {
|
||||
let serverError = (error as? ServerError) ?? ServerError.unknown
|
||||
throw LoginError.make(serverError: serverError)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension Authenticator {
|
||||
func createPendingAccount(params: CreatePendingAccountParams) -> AnyPublisher<UserProfile, LoginError> {
|
||||
let encodedParams = (try? JSONEncoder().encode(params)) ?? Data()
|
||||
|
||||
return networker
|
||||
.createPendingUserDep(params: encodedParams)
|
||||
.tryMap { [weak self] in
|
||||
self?.pendingUserToken = $0.pendingUserToken
|
||||
return $0.pendingUserProfile
|
||||
}
|
||||
.mapError { error in
|
||||
let serverError = (error as? ServerError) ?? ServerError.unknown
|
||||
return LoginError.make(serverError: serverError)
|
||||
}
|
||||
.eraseToAnyPublisher()
|
||||
func createPendingAccount(params: CreatePendingAccountParams) async throws -> UserProfile {
|
||||
do {
|
||||
let encodedParams = (try? JSONEncoder().encode(params)) ?? Data()
|
||||
let pendingUserAuthPayload = try await networker.createPendingUser(params: encodedParams)
|
||||
return pendingUserAuthPayload.pendingUserProfile
|
||||
} catch {
|
||||
throw LoginError.make(serverError: (error as? ServerError) ?? .unknown)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,18 +3,17 @@ import Foundation
|
||||
import Models
|
||||
|
||||
public extension Authenticator {
|
||||
func submitAppleToken(token: String) -> AnyPublisher<Void, LoginError> {
|
||||
networker
|
||||
.submitAppleToken(token: token)
|
||||
.tryMap { [weak self] in
|
||||
try ValetKey.authCookieString.setValue($0.commentedAuthCookieString)
|
||||
try ValetKey.authToken.setValue($0.authToken)
|
||||
self?.isLoggedIn = true
|
||||
func submitAppleToken(token: String) async throws {
|
||||
do {
|
||||
let authPayload = try await networker.submitAppleToken(token: token)
|
||||
try ValetKey.authCookieString.setValue(authPayload.commentedAuthCookieString)
|
||||
try ValetKey.authToken.setValue(authPayload.authToken)
|
||||
DispatchQueue.main.async {
|
||||
self.isLoggedIn = true
|
||||
}
|
||||
.mapError { error in
|
||||
let serverError = (error as? ServerError) ?? ServerError.unknown
|
||||
return LoginError.make(serverError: serverError)
|
||||
}
|
||||
.eraseToAnyPublisher()
|
||||
} catch {
|
||||
let serverError = (error as? ServerError) ?? ServerError.unknown
|
||||
throw LoginError.make(serverError: serverError)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
import Combine
|
||||
import Foundation
|
||||
import GoogleSignIn
|
||||
import Models
|
||||
@ -19,11 +18,9 @@ public final class Authenticator: ObservableObject {
|
||||
}
|
||||
|
||||
@Published public internal(set) var isLoggedIn: Bool
|
||||
@Published public var pendinguserProfile = UserProfile(username: "", name: "", bio: nil)
|
||||
|
||||
let networker: Networker
|
||||
|
||||
var subscriptions = Set<AnyCancellable>()
|
||||
var pendingUserToken: String?
|
||||
|
||||
public init(networker: Networker) {
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
import Combine
|
||||
import Foundation
|
||||
|
||||
extension Networker {
|
||||
func createAccount(params: Data) -> AnyPublisher<AuthPayload, ServerError> {
|
||||
func createAccount(params: Data) async throws -> AuthPayload {
|
||||
let urlRequest = URLRequest.create(
|
||||
baseURL: appEnvironment.serverBaseURL,
|
||||
urlPath: "/api/mobile-auth/create-account",
|
||||
@ -14,9 +13,10 @@ extension Networker {
|
||||
decode: AuthPayload.decode
|
||||
)
|
||||
|
||||
return urlSession
|
||||
.performRequest(resource: resource)
|
||||
.receive(on: DispatchQueue.main)
|
||||
.eraseToAnyPublisher()
|
||||
do {
|
||||
return try await urlSession.performReq(resource: resource)
|
||||
} catch {
|
||||
throw (error as? ServerError) ?? .unknown
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,27 +1,6 @@
|
||||
import Combine
|
||||
import Foundation
|
||||
import Models
|
||||
|
||||
extension Networker {
|
||||
func createPendingUserDep(params: Data) -> AnyPublisher<PendingUserAuthPayload, ServerError> {
|
||||
let urlRequest = URLRequest.create(
|
||||
baseURL: appEnvironment.serverBaseURL,
|
||||
urlPath: "/api/mobile-auth/sign-up",
|
||||
requestMethod: .post(params: params)
|
||||
)
|
||||
|
||||
let resource = ServerResource<PendingUserAuthPayload>(
|
||||
urlRequest: urlRequest,
|
||||
decode: PendingUserAuthPayload.decode
|
||||
)
|
||||
|
||||
return urlSession
|
||||
.performRequest(resource: resource)
|
||||
.receive(on: DispatchQueue.main)
|
||||
.eraseToAnyPublisher()
|
||||
}
|
||||
}
|
||||
|
||||
extension Networker {
|
||||
func createPendingUser(params: Data) async throws -> PendingUserAuthPayload {
|
||||
let urlRequest = URLRequest.create(
|
||||
|
||||
@ -1,26 +0,0 @@
|
||||
import Combine
|
||||
import Foundation
|
||||
import Models
|
||||
|
||||
extension Networker {
|
||||
func submitAppleToken(token: String) -> AnyPublisher<AuthPayload, ServerError> {
|
||||
let params = SignInParams(token: token, provider: .apple)
|
||||
let encodedParams = (try? JSONEncoder().encode(params)) ?? Data()
|
||||
|
||||
let urlRequest = URLRequest.create(
|
||||
baseURL: appEnvironment.serverBaseURL,
|
||||
urlPath: "/api/mobile-auth/sign-in",
|
||||
requestMethod: .post(params: encodedParams)
|
||||
)
|
||||
|
||||
let resource = ServerResource<AuthPayload>(
|
||||
urlRequest: urlRequest,
|
||||
decode: AuthPayload.decode
|
||||
)
|
||||
|
||||
return urlSession
|
||||
.performRequest(resource: resource)
|
||||
.receive(on: DispatchQueue.main)
|
||||
.eraseToAnyPublisher()
|
||||
}
|
||||
}
|
||||
@ -2,8 +2,17 @@ import Foundation
|
||||
import Models
|
||||
|
||||
extension Networker {
|
||||
func submitAppleToken(token: String) async throws -> AuthPayload {
|
||||
let params = SignInParams(token: token, provider: .apple)
|
||||
return try await submitSignInParams(params: params)
|
||||
}
|
||||
|
||||
func submitGoogleToken(idToken: String) async throws -> AuthPayload {
|
||||
let params = SignInParams(token: idToken, provider: .google)
|
||||
return try await submitSignInParams(params: params)
|
||||
}
|
||||
|
||||
func submitSignInParams(params: SignInParams) async throws -> AuthPayload {
|
||||
let encodedParams = (try? JSONEncoder().encode(params)) ?? Data()
|
||||
|
||||
let urlRequest = URLRequest.create(
|
||||
Reference in New Issue
Block a user