Skip to content

Commit

Permalink
Adding KMM back to iOS app, using for login (#149)
Browse files Browse the repository at this point in the history
* add task

* adding kmm.

SAVEPOINT.  CRASHES ON LOGOUT.

* Add back in KMM.
Start hooking up login use cases

* Fix login with google on andrid

* Rebase

---------

Co-authored-by: Cristhian Escobar <[email protected]>
  • Loading branch information
martyu and cristhianescobar authored Oct 28, 2023
1 parent 9a8b600 commit fb46339
Show file tree
Hide file tree
Showing 45 changed files with 717 additions and 595 deletions.
28 changes: 28 additions & 0 deletions .run/newm-mobile_shared [assembleXCFramework].run.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="newm-mobile:shared [assembleXCFramework]" type="GradleRunConfiguration" factoryName="Gradle">
<ExternalSystemSettings>
<option name="env">
<map>
<entry key="DEVELOPER_DIR" value="/Applications/Xcode.app/Contents/Developer" />
</map>
</option>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$/shared" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="assembleXCFramework" />
</list>
</option>
<option name="vmOptions" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<method v="2" />
</configuration>
</component>
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ val viewModule = module {
WelcomeScreenPresenter(
navigator = params.get(),
googleSignInLauncher = get(),
repository = get(),
loginUseCase = get(),
activityResultContract = ActivityResultContracts.StartActivityForResult()
)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package io.newm.feature.login.screen.welcome

import android.content.Intent
import android.util.Log
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.ActivityResult
import androidx.activity.result.contract.ActivityResultContract
Expand All @@ -22,12 +21,12 @@ import io.newm.feature.login.screen.LoginScreen
import io.newm.feature.login.screen.authproviders.google.GoogleSignInLauncher
import io.newm.feature.login.screen.createaccount.CreateAccountScreen
import io.newm.shared.login.repository.KMMException
import io.newm.shared.login.repository.LogInRepository
import io.newm.shared.login.repository.OAuthData
import io.newm.shared.usecases.LoginUseCase

class WelcomeScreenPresenter(
private val navigator: Navigator,
private val repository: LogInRepository,
private val loginUseCase: LoginUseCase,
private val googleSignInLauncher: GoogleSignInLauncher,
private val activityResultContract: ActivityResultContract<Intent, ActivityResult>,
) : Presenter<WelcomeScreenUiState> {
Expand Down Expand Up @@ -56,7 +55,7 @@ class WelcomeScreenPresenter(
val idToken = account.idToken
idToken ?: throw IllegalStateException("Google sign in failed. idToken is null")

repository.oAuthLogin(OAuthData.Google(idToken))
loginUseCase.logInWithGoogle(idToken)
navigator.goTo(HomeScreen)
} catch (e: ApiException) {
// The ApiException status code indicates the detailed failure reason.
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ android.useAndroidX=true
#MPP
kotlin.mpp.enableCInteropCommonization=true
kotlin.native.binary.memoryModel=experimental
kotlin.mpp.androidSourceSetLayoutVersion=2
kotlin.mpp.androidSourceSetLayoutVersion=2
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import Foundation
import shared

public extension Error {
var kmmException: KMMException? { (self as NSError).kotlinException as? KMMException }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import Foundation

public extension NotificationCenter {
func publisher(for name: String) -> Publisher {
publisher(for: Notification.Name(name), object: nil)
}
}
38 changes: 19 additions & 19 deletions iosApp/Modules/DI/ModuleLinker/Protocols/Data.swift
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
import Foundation
import Models

public protocol UserManaging: ObservableObject {
var currentUser: User? { get }

func deleteUser() async throws
func createUser(nickname: String, email: String, password: String, passwordConfirmation: String, verificationCode: String) async throws
func resetPassword(email: String, password: String, confirmPassword: String, authCode: String) async throws
func fetchCurrentUser() async throws
func updateUserInfo(firstName: String?, lastName: String?, currentPassword: String?, newPassword: String?, confirmNewPassword: String?) async throws
}

public enum UserRepoError: LocalizedError {
case accountExists
case twoFAFailed
case dataUnavailable
case displayError(String)
}
//import Foundation
//import Models
//
//public protocol UserManaging: ObservableObject {
// var currentUser: User? { get }
//
// func deleteUser() async throws
// func createUser(nickname: String, email: String, password: String, passwordConfirmation: String, verificationCode: String) async throws
// func resetPassword(email: String, password: String, confirmPassword: String, authCode: String) async throws
// func fetchCurrentUser() async throws
// func updateUserInfo(firstName: String?, lastName: String?, currentPassword: String?, newPassword: String?, confirmNewPassword: String?) async throws
//}
//
//public enum UserRepoError: LocalizedError {
// case accountExists
// case twoFAFailed
// case dataUnavailable
// case displayError(String)
//}
3 changes: 0 additions & 3 deletions iosApp/Modules/Data/DataModule.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,6 @@ public final class DataModule: ModuleProtocol {
public static let shared = DataModule()

public func registerAllServices() {
Resolver.register {
UserRepo.shared as any UserManaging
}
}
}

Expand Down
137 changes: 67 additions & 70 deletions iosApp/Modules/Data/Login/LoginRepo.swift
Original file line number Diff line number Diff line change
@@ -1,70 +1,67 @@
import Foundation
import API
import KeychainSwift
import FacebookLogin
import GoogleSignIn
import AuthenticationServices

enum LoginError: Error {
case facebookAccessTokenMissing
}

public class LoginRepo: ObservableObject {
//TODO: update this with user info
@Published public var userIsLoggedIn: Bool = false
private let api: LoginAPI

private var appleSignInID: String?

//TODO: make actor
public static let shared = LoginRepo()

private init(api: LoginAPI = LoginAPI()) {
self.api = api
api.$userIsLoggedIn.assign(to: &$userIsLoggedIn)
}

public func loginWithFacebook(result: LoginManagerLoginResult) async throws {
do {
guard let token = result.token?.tokenString else {
throw LoginError.facebookAccessTokenMissing
}
try await api.login(method: .facebook(accessToken: token))
} catch {
Task { @MainActor in
FacebookLogin.LoginManager().logOut()
}
throw error
}
}

public func loginWithGoogle(result: GIDSignInResult) async throws {
let token = result.user.accessToken.tokenString
try await api.login(method: .google(accessToken: token))
}

public func login(email: String, password: String) async throws {
try await api.login(method: .email(email: email, password: password))
}

public func logOut() {
api.logOut()
FacebookLogin.LoginManager().logOut()
GIDSignIn.sharedInstance.signOut()
signOutOfApple()
UserRepo.shared.currentUser = nil
}

public func requestEmailVerificationCode(for email: String) async throws {
try await api.requestEmailVerificationCode(for: email)
}

public func loginWithApple(result: ASAuthorization) async throws {
let token = String(data: (result.credential as! ASAuthorizationAppleIDCredential).identityToken!, encoding: .utf8)!
try await api.login(method: .apple(idToken: token))
}

private func signOutOfApple() {
//TODO:
}
}
//import Foundation
//import API
//import KeychainSwift
//import FacebookLogin
//import GoogleSignIn
//import AuthenticationServices
//
//enum LoginError: Error {
// case facebookAccessTokenMissing
//}
//
//public class LoginRepo: ObservableObject {
// //TODO: update this with user info
// @Published public var userIsLoggedIn: Bool = false
// private let api: LoginAPI
//
// private var appleSignInID: String?
//
// private init(api: LoginAPI = LoginAPI()) {
// self.api = api
// api.$userIsLoggedIn.assign(to: &$userIsLoggedIn)
// }
//
// public func loginWithFacebook(result: LoginManagerLoginResult) async throws {
// do {
// guard let token = result.token?.tokenString else {
// throw LoginError.facebookAccessTokenMissing
// }
// try await api.login(method: .facebook(accessToken: token))
// } catch {
// Task { @MainActor in
// FacebookLogin.LoginManager().logOut()
// }
// throw error
// }
// }
//
// public func loginWithGoogle(result: GIDSignInResult) async throws {
// let token = result.user.accessToken.tokenString
// try await api.login(method: .google(accessToken: token))
// }
//
// public func login(email: String, password: String) async throws {
// try await api.login(method: .email(email: email, password: password))
// }
//
// public func logOut() {
// api.logOut()
// FacebookLogin.LoginManager().logOut()
// GIDSignIn.sharedInstance.signOut()
// signOutOfApple()
// UserRepo.shared.currentUser = nil
// }
//
// public func requestEmailVerificationCode(for email: String) async throws {
// try await api.requestEmailVerificationCode(for: email)
// }
//
// public func loginWithApple(result: ASAuthorization) async throws {
// let token = String(data: (result.credential as! ASAuthorizationAppleIDCredential).identityToken!, encoding: .utf8)!
// try await api.login(method: .apple(idToken: token))
// }
//
// private func signOutOfApple() {
// //TODO:
// }
//}
Loading

0 comments on commit fb46339

Please sign in to comment.