-
Notifications
You must be signed in to change notification settings - Fork 2
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
[FEAT/#7] kakao login #12
Changes from 6 commits
ffec005
e0a464a
8f32a72
95049f1
480aa33
a9fd720
19cc191
6048c07
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 |
---|---|---|
|
@@ -14,4 +14,4 @@ buildscript { | |
|
||
tasks.register("clean", Delete::class) { | ||
delete(rootProject.buildDir) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,4 +5,4 @@ object Constants { | |
const val targetSdk = 34 | ||
const val versionCode = 1 | ||
const val versionName = "1.0" | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package com.going.domain.entity.response | ||
|
||
data class AuthTokenModel( | ||
val isResigned: Boolean, | ||
val accessToken: String, | ||
val refreshToken: String, | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
package com.going.presentation.auth | ||
|
||
import android.os.Bundle | ||
import androidx.activity.viewModels | ||
import androidx.lifecycle.flowWithLifecycle | ||
import androidx.lifecycle.lifecycleScope | ||
import com.going.presentation.R | ||
import com.going.presentation.databinding.ActivityLoginBinding | ||
import com.going.ui.base.BaseActivity | ||
import com.going.ui.extension.UiState | ||
import com.going.ui.extension.setOnSingleClickListener | ||
import kotlinx.coroutines.flow.launchIn | ||
import kotlinx.coroutines.flow.onEach | ||
|
||
class LoginActivity : BaseActivity<ActivityLoginBinding>(R.layout.activity_login) { | ||
private val viewModel by viewModels<LoginViewModel>() | ||
|
||
override fun onCreate(savedInstanceState: Bundle?) { | ||
super.onCreate(savedInstanceState) | ||
|
||
initKakaoLoginButtonClickListener() | ||
observeInfo() | ||
} | ||
|
||
private fun initKakaoLoginButtonClickListener() { | ||
binding.btnSignIn.setOnSingleClickListener { | ||
viewModel.startKakaoLogIn(this) | ||
} | ||
} | ||
|
||
private fun observeInfo() { | ||
observeIsAppLoginAvailable() | ||
observePostChangeTokenState() | ||
} | ||
Comment on lines
+31
to
+34
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. 두개정도면 따로 함수화 추가적으로 진행 안하고 onCreate에 observe 함수 두개 두는건 어떨까나요 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. 이 부분은 앞으로 observe 할 값이 많아질 것이라고 예상돼서 묶어뒀습니다! |
||
|
||
private fun observeIsAppLoginAvailable() { | ||
viewModel.isAppLoginAvailable.flowWithLifecycle(lifecycle).onEach { canLogin -> | ||
if (!canLogin) viewModel.startKakaoLogIn(this) | ||
}.launchIn(lifecycleScope) | ||
} | ||
|
||
private fun observePostChangeTokenState() { | ||
viewModel.postChangeTokenState.flowWithLifecycle(lifecycle).onEach { tokenState -> | ||
when (tokenState) { | ||
is UiState.Success -> { | ||
// 성공 했을 때 로직 | ||
} | ||
|
||
is UiState.Failure -> { | ||
// 실패 했을 때 로직 | ||
} | ||
|
||
is UiState.Empty -> { | ||
// 여튼 로직 | ||
} | ||
|
||
is UiState.Loading -> { | ||
// 로딩 중 로직 | ||
} | ||
} | ||
}.launchIn(lifecycleScope) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
package com.going.presentation.auth | ||
|
||
import android.content.Context | ||
import androidx.lifecycle.ViewModel | ||
import androidx.lifecycle.viewModelScope | ||
import com.going.domain.entity.response.AuthTokenModel | ||
import com.going.ui.extension.UiState | ||
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 kotlinx.coroutines.flow.MutableStateFlow | ||
import kotlinx.coroutines.flow.StateFlow | ||
import kotlinx.coroutines.launch | ||
|
||
class LoginViewModel : ViewModel() { | ||
private val _postChangeTokenState = MutableStateFlow<UiState<AuthTokenModel>>(UiState.Empty) | ||
val postChangeTokenState: StateFlow<UiState<AuthTokenModel?>> = _postChangeTokenState | ||
|
||
private val _isAppLoginAvailable = MutableStateFlow(true) | ||
val isAppLoginAvailable: StateFlow<Boolean> = _isAppLoginAvailable | ||
|
||
private var webLoginCallback: (OAuthToken?, Throwable?) -> Unit = { token, error -> | ||
if (error == null && token != null) { | ||
changeTokenFromServer( | ||
accessToken = token.accessToken, | ||
) | ||
} | ||
} | ||
|
||
private var appLoginCallback: (OAuthToken?, Throwable?) -> Unit = { token, error -> | ||
if (error != null) { | ||
// 뒤로가기 경우 예외 처리 | ||
if (!(error is ClientError && error.reason == ClientErrorCause.Cancelled)) { | ||
_isAppLoginAvailable.value = false | ||
} | ||
} else if (token != null) { | ||
changeTokenFromServer( | ||
accessToken = token.accessToken, | ||
) | ||
} | ||
} | ||
|
||
fun startKakaoLogIn(context: Context) { | ||
if (UserApiClient.instance.isKakaoTalkLoginAvailable(context) && isAppLoginAvailable.value) { | ||
UserApiClient.instance.loginWithKakaoTalk( | ||
context = context, | ||
callback = appLoginCallback, | ||
) | ||
} else { | ||
UserApiClient.instance.loginWithKakaoAccount( | ||
context = context, | ||
callback = webLoginCallback, | ||
) | ||
} | ||
} | ||
|
||
// 서버통신 - 카카오 토큰 보내서 서비스 토큰 받아오기 - 서버와 협의 후 수정예정 | ||
private fun changeTokenFromServer( | ||
accessToken: String, | ||
social: String = KAKAO, | ||
) { | ||
_postChangeTokenState.value = UiState.Loading | ||
|
||
viewModelScope.launch { | ||
// 통신 로직 | ||
|
||
// 성공시 서버에서 준 정보를 넣는 예시 코드 | ||
_postChangeTokenState.value = UiState.Success( | ||
AuthTokenModel( | ||
isResigned = true, | ||
accessToken = "testAccessToekn", | ||
refreshToken = "testRefreshToekn", | ||
), | ||
) | ||
} | ||
} | ||
|
||
companion object { | ||
const val KAKAO = "KAKAO" | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<layout xmlns:android="http://schemas.android.com/apk/res/android" | ||
xmlns:app="http://schemas.android.com/apk/res-auto"> | ||
|
||
<data> | ||
|
||
</data> | ||
|
||
<androidx.constraintlayout.widget.ConstraintLayout | ||
android:layout_width="match_parent" | ||
android:layout_height="match_parent"> | ||
|
||
<TextView | ||
android:id="@+id/tv_sign_in_title" | ||
android:layout_width="match_parent" | ||
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. match_parent 대신 0dp를 사용합시당 ~ 아마 그러면 android:gravity="center" 도 안해도 될듯 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. 이건 자꾸 까먹네요... 습관 들이게 노력하겠습니다 :) |
||
android:layout_height="wrap_content" | ||
android:layout_marginHorizontal="16dp" | ||
android:layout_marginBottom="8dp" | ||
android:gravity="center" | ||
android:lineHeight="42dp" | ||
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. lineHeight 한줄로 설정해두는 것들도 typo에 넣어뒀으니 나중에 UI 수정할때 활용하면 좋을듯합니닷 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. 이 부분은 추후에 디자인이 확정되고, 전체 수정할때 참고하도록 하겠습니다! |
||
android:text="@string/sign_in_tv_title" | ||
android:textColor="@color/white" | ||
app:layout_constraintBottom_toTopOf="@id/iv_sign_in" | ||
app:layout_constraintEnd_toEndOf="parent" | ||
app:layout_constraintStart_toStartOf="parent" /> | ||
|
||
<ImageView | ||
android:id="@+id/iv_sign_in" | ||
android:layout_width="0dp" | ||
android:layout_height="0dp" | ||
android:minHeight="340dp" | ||
android:scaleType="centerCrop" | ||
android:src="@drawable/img_sign_in_main" | ||
app:layout_constraintBottom_toBottomOf="parent" | ||
app:layout_constraintDimensionRatio="1" | ||
app:layout_constraintEnd_toEndOf="parent" | ||
app:layout_constraintStart_toStartOf="parent" | ||
app:layout_constraintTop_toTopOf="parent" /> | ||
|
||
<ImageView | ||
android:id="@+id/btn_sign_in" | ||
android:layout_width="match_parent" | ||
android:layout_height="wrap_content" | ||
android:layout_marginHorizontal="16dp" | ||
android:src="@drawable/img_sign_in_kakao_button" | ||
app:layout_constraintBottom_toBottomOf="parent" | ||
app:layout_constraintEnd_toEndOf="parent" | ||
app:layout_constraintStart_toStartOf="parent" | ||
app:layout_constraintTop_toBottomOf="@id/iv_sign_in" /> | ||
|
||
<TextView | ||
android:id="@+id/tv_sign_in_terms" | ||
android:layout_width="match_parent" | ||
android:layout_height="wrap_content" | ||
android:layout_marginHorizontal="16dp" | ||
android:layout_marginTop="12dp" | ||
android:layout_marginBottom="8dp" | ||
android:gravity="center" | ||
android:lineHeight="42dp" | ||
android:text="@string/sign_in_tv_terms" | ||
android:textColor="@color/white" | ||
app:layout_constraintTop_toBottomOf="@id/btn_sign_in" | ||
app:layout_constraintEnd_toEndOf="parent" | ||
app:layout_constraintStart_toStartOf="parent" /> | ||
|
||
</androidx.constraintlayout.widget.ConstraintLayout> | ||
</layout> |
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.
요고 함수명 우리 ~ BtnClickListener 로 통일할까?
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.
넵! 이런 부분 공유 아주 조아용~