-
Notifications
You must be signed in to change notification settings - Fork 0
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
[Feature/#17] : 카카오 로그인, 구글 로그인 구현 #23
Changes from 21 commits
6cc59e2
0a85b39
75d90c3
947d5c1
d9aeacb
1877ed8
4d5e1b4
02e14d5
7a94617
c163649
d6fcf78
63cb4b7
a5e8114
f2c6643
a0a3cae
266ea84
51cc6f7
f061f87
2b3d783
97393e4
e2defe7
8eda530
1e6c6f9
fabd2a0
5b68ff8
c1a41b2
3cf60fd
3fc19ba
9061573
dfeb545
f98694d
fbc7d96
291d673
cc0e210
58eb933
116ba83
7703990
37978ae
2c39516
0beec3c
dca3aad
add7a4a
ce0045f
2048ee1
2d9b6a2
6de643c
5efe337
b0697ae
653148e
8392c52
7def1e9
e13ed44
4ef97c2
9b6a716
6b01f92
193ed71
a57b103
ebf1064
a2c272a
a079317
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package com.sopt.noostak.di | ||
|
||
import com.sopt.noostak.BuildConfig | ||
import dagger.Module | ||
import dagger.Provides | ||
import dagger.hilt.InstallIn | ||
import dagger.hilt.components.SingletonComponent | ||
import javax.inject.Named | ||
import javax.inject.Singleton | ||
|
||
@Module | ||
@InstallIn(SingletonComponent::class) | ||
object AuthModule { | ||
@Provides | ||
@Singleton | ||
@Named("GoogleClientId") | ||
fun provideGoogleClientId(): String { | ||
return BuildConfig.GOOGLE_CLIENT_ID | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,12 @@ | ||
package com.sopt.presentation.auth.login | ||
|
||
import androidx.annotation.StringRes | ||
|
||
sealed class LoginSideEffect { | ||
data object NavigateToHome : LoginSideEffect() | ||
data class NavigateSignUp(val authId: String) : LoginSideEffect() | ||
data class ShowToast( | ||
@StringRes val message: Int, | ||
val args: String? = null | ||
) : LoginSideEffect() | ||
} |
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P1 : 로컬에 token 저장하는 로직 필요할 것 같아요 member id랑.. refresh token은 안받나요? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 서버 연결 로직 작성 시 발급받는 accessToken과 refreshToken를 저장하려고 하는데 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 아아 생각해보니 아직 서버 연결 전이네용 ㅋㅋㅋ 서버 연결 기준으로 말한거였어요! 흠 그래도 로컬에 토큰 제외하고 유저 정보 저장하는건 구현해놓으면 좋을 것 같아용 member id, nickname, ... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 넵! 해당 부분 수정하겠습니다!! |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,26 +1,94 @@ | ||
package com.sopt.presentation.auth.login | ||
|
||
import android.content.Context | ||
import androidx.activity.result.ActivityResultLauncher | ||
import androidx.activity.result.IntentSenderRequest | ||
import androidx.annotation.StringRes | ||
import com.google.android.gms.auth.api.identity.Identity | ||
import com.google.android.gms.auth.api.identity.SignInClient | ||
import com.google.android.gms.auth.api.identity.SignInCredential | ||
import com.kakao.sdk.auth.model.OAuthToken | ||
import com.kakao.sdk.common.model.ClientError | ||
import com.kakao.sdk.common.model.ClientErrorCause | ||
import com.kakao.sdk.user.UserApiClient | ||
import com.sopt.core.util.BaseViewModel | ||
import com.sopt.presentation.R | ||
import dagger.hilt.android.lifecycle.HiltViewModel | ||
import kotlinx.coroutines.flow.MutableStateFlow | ||
import kotlinx.coroutines.flow.StateFlow | ||
import javax.inject.Inject | ||
import javax.inject.Named | ||
|
||
@HiltViewModel | ||
class LoginViewModel @Inject constructor() : BaseViewModel<LoginSideEffect>() { | ||
class LoginViewModel @Inject constructor( | ||
@Named("GoogleClientId") private val googleClientId: String | ||
) : BaseViewModel<LoginSideEffect>() { | ||
private val _authId = MutableStateFlow("") | ||
val authId: StateFlow<String> = _authId | ||
private lateinit var oneTapClient: SignInClient | ||
|
||
private val _authId = MutableStateFlow<String?>(null) | ||
val authId: StateFlow<String?> = _authId | ||
fun initializeGoogleSignIn(context: Context) { | ||
oneTapClient = Identity.getSignInClient(context) | ||
} | ||
|
||
// Kakao Login | ||
fun kakaoLogin(context: Context) { | ||
val loginCallback: (OAuthToken?, Throwable?) -> Unit = { token, error -> | ||
if (error != null) { | ||
handleError(error, R.string.toast_kakao_login_failed) | ||
} else if (token != null) { | ||
handleSuccess(token.accessToken, R.string.toast_kakao_login_success) | ||
} | ||
} | ||
|
||
if (UserApiClient.instance.isKakaoTalkLoginAvailable(context)) { | ||
UserApiClient.instance.loginWithKakaoTalk(context, callback = loginCallback) | ||
} else { | ||
UserApiClient.instance.loginWithKakaoAccount(context, callback = loginCallback) | ||
} | ||
} | ||
|
||
// Google Login | ||
fun googleLogin(launcher: ActivityResultLauncher<IntentSenderRequest>) { | ||
val signInRequest = com.google.android.gms.auth.api.identity.BeginSignInRequest.builder() | ||
.setGoogleIdTokenRequestOptions( | ||
com.google.android.gms.auth.api.identity.BeginSignInRequest.GoogleIdTokenRequestOptions.builder() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P1: 요거 임포트 해주세요!! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P2: Credential Manager로 리팩해보면 좋을 것 같아요!! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 네ㅔㅔㅔ 리팩해놓겠슴다ㅏㅏ |
||
.setSupported(true) | ||
.setServerClientId(googleClientId) | ||
.setFilterByAuthorizedAccounts(false) | ||
.build() | ||
) | ||
.build() | ||
|
||
fun kakaoLogin() { | ||
// TODO: 카카오 로그인 | ||
navigateToHome() | ||
oneTapClient.beginSignIn(signInRequest) | ||
.addOnSuccessListener { result -> | ||
launcher.launch(IntentSenderRequest.Builder(result.pendingIntent).build()) | ||
} | ||
.addOnFailureListener { exception -> | ||
handleError(exception, R.string.toast_google_login_failed) | ||
} | ||
} | ||
|
||
fun googleLogin() { | ||
// TODO: 구글 로그인 | ||
_authId.value = "google_access_token" | ||
navigateToSignup(_authId.value.orEmpty()) | ||
fun handleGoogleLoginResult(credential: SignInCredential) { | ||
if (!credential.googleIdToken.isNullOrEmpty()) { | ||
handleSuccess(credential.googleIdToken.toString(), R.string.toast_google_login_success) | ||
} else { | ||
showToast(R.string.toast_google_login_failed) | ||
} | ||
} | ||
|
||
private fun handleSuccess(authId: String, successMessageResId: Int) { | ||
_authId.value = authId | ||
showToast(successMessageResId) | ||
navigateToSignup(authId) | ||
} | ||
|
||
private fun handleError(error: Throwable, @StringRes errorMessageResId: Int) { | ||
if (error is ClientError && error.reason == ClientErrorCause.Cancelled) { | ||
showToast(R.string.toast_login_cancelled) | ||
} else { | ||
showToast(errorMessageResId, error.localizedMessage.orEmpty()) | ||
} | ||
} | ||
|
||
private fun navigateToSignup(authId: String) { | ||
|
@@ -30,4 +98,13 @@ class LoginViewModel @Inject constructor() : BaseViewModel<LoginSideEffect>() { | |
private fun navigateToHome() { | ||
emitSideEffect(LoginSideEffect.NavigateToHome) | ||
} | ||
|
||
private fun showToast(@StringRes messageResId: Int, vararg formatArgs: String) { | ||
emitSideEffect( | ||
LoginSideEffect.ShowToast( | ||
message = messageResId, | ||
args = formatArgs.joinToString(separator = ", ") | ||
) | ||
) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
P3 : 실패했을 때 뜨는 스낵바나 다이얼로그 GUI 필요할듯요
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
넵 추가하겠습니다!