Skip to content

Commit

Permalink
wip: integrate sign in with apple
Browse files Browse the repository at this point in the history
  • Loading branch information
cp-megh-l committed Oct 8, 2024
1 parent 02c5422 commit c78fe78
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@ import com.canopas.yourspace.data.utils.AppDispatcher
import com.canopas.yourspace.ui.navigation.AppDestinations
import com.canopas.yourspace.ui.navigation.AppNavigator
import com.google.android.gms.auth.api.signin.GoogleSignInAccount
import com.google.firebase.auth.AuthResult
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch
import kotlinx.coroutines.tasks.await
import timber.log.Timber
import javax.inject.Inject

Expand All @@ -33,12 +35,12 @@ class SignInMethodViewModel @Inject constructor(
_state.emit(_state.value.copy(showGoogleLoading = true))
try {
val firebaseToken = firebaseAuth.signInWithGoogleAuthCredential(account.idToken)
val isNewUSer = authService.verifiedGoogleLogin(
val isNewUser = authService.verifiedGoogleLogin(
firebaseAuth.currentUserUid,
firebaseToken,
account
)
onSignUp(isNewUSer)
onSignUp(isNewUser)
_state.emit(_state.value.copy(showGoogleLoading = false))
} catch (e: Exception) {
Timber.e(e, "Failed to sign in with google")
Expand All @@ -51,11 +53,34 @@ class SignInMethodViewModel @Inject constructor(
}
}

fun proceedAppleSignIn(authResult: AuthResult) =
viewModelScope.launch(appDispatcher.IO) {
_state.emit(_state.value.copy(showAppleLoading = true))
try {
val firebaseToken = authResult.user?.getIdToken(true)?.await()
val isNewUser = authService.verifiedAppleLogin(
firebaseAuth.currentUserUid,
firebaseToken?.token ?: "",
authResult.user!!
)
onSignUp(isNewUser)
_state.emit(_state.value.copy(showAppleLoading = false))
} catch (e: Exception) {
Timber.e(e, "Failed to sign in with Apple")
_state.emit(
_state.value.copy(
showAppleLoading = false,
error = e
)
)
}
}

fun resetErrorState() {
_state.value = _state.value.copy(error = null)
}

fun onSignUp(isNewUSer: Boolean) = viewModelScope.launch(appDispatcher.MAIN) {
private fun onSignUp(isNewUSer: Boolean) = viewModelScope.launch(appDispatcher.MAIN) {
if (isNewUSer) {
navigator.navigateTo(
AppDestinations.onboard.path,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ import com.canopas.yourspace.ui.theme.CatchMeTheme
import com.google.android.gms.auth.api.signin.GoogleSignIn
import com.google.android.gms.auth.api.signin.GoogleSignInOptions
import com.google.android.gms.common.api.ApiException
import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.auth.OAuthProvider
import timber.log.Timber

@Composable
Expand Down Expand Up @@ -136,12 +138,32 @@ private fun GoogleSignInBtn() {

@Composable
fun AppleSignInBtn() {
val context = LocalContext.current
val context = LocalContext.current as Activity
val viewModel = hiltViewModel<SignInMethodViewModel>()
val state by viewModel.state.collectAsState()

PrimaryTextButton(
onClick = { /*TODO*/ },
onClick = {
val provider = OAuthProvider.newBuilder("apple.com")
provider.setScopes(arrayListOf("email", "name"))
FirebaseAuth.getInstance().pendingAuthResult?.addOnCompleteListener { task ->
if (task.isSuccessful) {
viewModel.proceedAppleSignIn(task.result)
} else {
Timber.e(task.exception, "Apple sign-in failed")
}
} ?: run {
FirebaseAuth.getInstance()
.startActivityForSignInWithProvider(context, provider.build())
.addOnCompleteListener { task ->
if (task.isSuccessful) {
viewModel.proceedAppleSignIn(task.result)
} else {
Timber.e(task.exception, "Apple sign-in failed")
}
}
}
},
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import com.canopas.yourspace.data.storage.LocationCache
import com.canopas.yourspace.data.storage.UserPreferences
import com.google.android.gms.auth.api.signin.GoogleSignInAccount
import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.auth.FirebaseUser
import javax.inject.Inject
import javax.inject.Singleton

Expand Down Expand Up @@ -37,12 +38,21 @@ class AuthService @Inject constructor(
return processLogin(uid, firebaseToken, account)
}

suspend fun verifiedAppleLogin(
uid: String?,
firebaseToken: String?,
account: FirebaseUser
): Boolean {
return processLogin(uid, firebaseToken, null, firebaseAccount = account)
}

private suspend fun processLogin(
uid: String?,
firebaseToken: String?,
account: GoogleSignInAccount? = null
account: GoogleSignInAccount? = null,
firebaseAccount: FirebaseUser? = null
): Boolean {
val (isNewUser, user, session) = apiUserService.saveUser(uid, firebaseToken, account)
val (isNewUser, user, session) = apiUserService.saveUser(uid, firebaseToken, account, firebaseAccount)
notifyAuthChange()
saveUser(user, session)
return isNewUser
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import com.canopas.yourspace.data.utils.Config.FIRESTORE_COLLECTION_USERS
import com.canopas.yourspace.data.utils.Device
import com.canopas.yourspace.data.utils.snapshotFlow
import com.google.android.gms.auth.api.signin.GoogleSignInAccount
import com.google.firebase.auth.FirebaseUser
import com.google.firebase.firestore.FieldValue
import com.google.firebase.firestore.FirebaseFirestore
import com.google.firebase.functions.FirebaseFunctions
Expand Down Expand Up @@ -51,7 +52,8 @@ class ApiUserService @Inject constructor(
suspend fun saveUser(
uid: String?,
firebaseToken: String?,
account: GoogleSignInAccount? = null
account: GoogleSignInAccount? = null,
firebaseUser: FirebaseUser? = null
): Triple<Boolean, ApiUser, ApiUserSession> {
val savedUser = if (uid.isNullOrEmpty()) null else getUser(uid)
val isExists = savedUser != null
Expand All @@ -74,10 +76,10 @@ class ApiUserService @Inject constructor(
id = uid!!,
email = account?.email ?: "",
auth_type = if (account != null) LOGIN_TYPE_GOOGLE else 0,
first_name = account?.givenName ?: "",
first_name = account?.givenName ?: firebaseUser?.displayName ?: "",
last_name = account?.familyName ?: "",
provider_firebase_id_token = firebaseToken,
profile_image = account?.photoUrl?.toString() ?: ""
profile_image = account?.photoUrl?.toString() ?: firebaseUser?.photoUrl?.toString() ?: ""
)
userRef.document(uid).set(user).await()
val sessionDocRef = sessionRef(user.id).document()
Expand Down

0 comments on commit c78fe78

Please sign in to comment.