Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LoginViewModel - Context 참조 제거 #64

Merged
merged 4 commits into from
Oct 28, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package com.goalpanzi.mission_mate.feature.login

import android.content.Context
import androidx.credentials.CredentialManager
import androidx.credentials.CustomCredential
import androidx.credentials.GetCredentialRequest
import androidx.credentials.GetCredentialResponse
import com.google.android.libraries.identity.googleid.GetSignInWithGoogleOption
import com.google.android.libraries.identity.googleid.GoogleIdTokenCredential
import com.google.android.libraries.identity.googleid.GoogleIdTokenParsingException
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext

sealed class LoginData {
data class Success(val email : String) : LoginData()
data class Failed(val exception: Exception) : LoginData()
}

class LoginManager (
private val context : Context
) {
suspend fun request() : LoginData = withContext(Dispatchers.IO) {
val credentialManager = CredentialManager.create(context)
val signInWithGoogleOption: GetSignInWithGoogleOption =
GetSignInWithGoogleOption.Builder(BuildConfig.CREDENTIAL_WEB_CLIENT_ID)
.build()

val request: GetCredentialRequest = GetCredentialRequest.Builder()
.addCredentialOption(signInWithGoogleOption)
.build()

return@withContext try {
val result = credentialManager.getCredential(context, request)
handleSignIn(result)
} catch (e: Exception) {
e.printStackTrace()
LoginData.Failed(e)
}
}

private fun handleSignIn(response: GetCredentialResponse) : LoginData {
return when (val credential = response.credential) {
is CustomCredential -> {
if (credential.type == GoogleIdTokenCredential.TYPE_GOOGLE_ID_TOKEN_CREDENTIAL) {
try {
val googleIdTokenCredential = GoogleIdTokenCredential.createFrom(credential.data)
LoginData.Success(googleIdTokenCredential.id)
} catch (e: GoogleIdTokenParsingException) {
LoginData.Failed(e)
}
}else {
LoginData.Failed(RuntimeException("Credential Type not equals TYPE_GOOGLE_ID_TOKEN_CREDENTIAL"))
bywindow marked this conversation as resolved.
Show resolved Hide resolved
}
}

else -> {
LoginData.Failed(RuntimeException("Credential is not CustomCredential"))
bywindow marked this conversation as resolved.
Show resolved Hide resolved
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,14 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.navigationBarsPadding
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.statusBarsPadding
import androidx.compose.foundation.layout.widthIn
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
Expand All @@ -33,16 +34,18 @@ import androidx.hilt.navigation.compose.hiltViewModel
import com.goalpanzi.mission_mate.core.designsystem.theme.ColorWhite_FFFFFFFF
import com.goalpanzi.mission_mate.core.designsystem.theme.Color_FFFF5632
import com.goalpanzi.mission_mate.core.designsystem.theme.MissionMateTypography
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch

@Composable
fun LoginRoute(
onLoginSuccess: (Boolean) -> Unit,
modifier: Modifier = Modifier,
coroutineScope : CoroutineScope = rememberCoroutineScope(),
loginManager: LoginManager = rememberLoginManager(),
viewModel: LoginViewModel = hiltViewModel()
) {
val context = LocalContext.current

LaunchedEffect(true) {
viewModel.eventFlow.collectLatest {
when (it) {
Expand All @@ -54,10 +57,22 @@ fun LoginRoute(

LoginScreen(
modifier = modifier,
onGoogleLoginClick = { viewModel.request(context) }
onGoogleLoginClick = {
coroutineScope.launch {
viewModel.login(loginManager.request())
}
bywindow marked this conversation as resolved.
Show resolved Hide resolved
}
)
}

@Composable
private fun rememberLoginManager(): LoginManager {
val context = LocalContext.current
return remember {
LoginManager(context)
}
}

@Composable
fun LoginScreen(
modifier: Modifier = Modifier,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,8 @@
package com.goalpanzi.mission_mate.feature.login

import android.content.Context
import androidx.credentials.CredentialManager
import androidx.credentials.CustomCredential
import androidx.credentials.GetCredentialRequest
import androidx.credentials.GetCredentialResponse
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.goalpanzi.mission_mate.core.domain.auth.usecase.LoginUseCase
import com.google.android.libraries.identity.googleid.GetSignInWithGoogleOption
import com.google.android.libraries.identity.googleid.GoogleIdTokenCredential
import com.google.android.libraries.identity.googleid.GoogleIdTokenParsingException
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.asSharedFlow
Expand All @@ -25,48 +17,26 @@ class LoginViewModel @Inject constructor(
private val _eventFlow = MutableSharedFlow<LoginEvent>()
val eventFlow = _eventFlow.asSharedFlow()

fun request(context: Context) {
viewModelScope.launch {
val credentialManager = CredentialManager.create(context)
val signInWithGoogleOption: GetSignInWithGoogleOption =
GetSignInWithGoogleOption.Builder(BuildConfig.CREDENTIAL_WEB_CLIENT_ID)
.build()

val request: GetCredentialRequest = GetCredentialRequest.Builder()
.addCredentialOption(signInWithGoogleOption)
.build()

try {
val result = credentialManager.getCredential(context, request)
handleSignIn(result)
} catch (e: Exception) {
e.printStackTrace()
}
}
}

private suspend fun handleSignIn(response: GetCredentialResponse) {
when (val credential = response.credential) {
is CustomCredential -> {
if (credential.type == GoogleIdTokenCredential.TYPE_GOOGLE_ID_TOKEN_CREDENTIAL) {
fun login(loginData: LoginData){
when(loginData){
is LoginData.Success -> {
viewModelScope.launch {
try {
val googleIdTokenCredential = GoogleIdTokenCredential.createFrom(credential.data)
val result = loginUseCase.requestGoogleLogin(email = googleIdTokenCredential.id)
val result = loginUseCase.requestGoogleLogin(email = loginData.email)
_eventFlow.emit(
result?.let {
LoginEvent.Success(it.isProfileSet)
} ?: run {
LoginEvent.Error
}
)
} catch (e: GoogleIdTokenParsingException) {
}catch (e: Exception){
e.printStackTrace()
}
}
}

else -> {
// TODO : error event
is LoginData.Failed -> {
loginData.exception.printStackTrace()
}
}
}
Expand Down
Loading