Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
2 changes: 1 addition & 1 deletion app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ android {
}

composeOptions {
kotlinCompilerExtensionVersion = "1.4.4"
kotlinCompilerExtensionVersion = "1.5.0"
}

splits {
Expand Down
23 changes: 0 additions & 23 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -117,13 +117,6 @@
android:scheme="kakao${KAKAO_NATIVE_APP_KEY}" />
</intent-filter>
</activity>
<activity
android:name=".presentation.base.BaseActivity"
android:exported="false">
<meta-data
android:name="android.app.lib_name"
android:value="" />
</activity>
<activity
android:name=".presentation.mypage.usernamechange.UserNameChangeActivity"
android:exported="true"
Expand Down Expand Up @@ -161,22 +154,6 @@
android:name="android.app.lib_name"
android:value="" />
</activity>
<activity
android:name=".presentation.review.report.OthersReviewDialogActivity"
android:exported="true"
android:theme="@style/Theme.MyDialog">
<meta-data
android:name="android.app.lib_name"
android:value="" />
</activity>
<activity
android:name=".presentation.common.MyReviewBottomSheetFragment"
android:exported="true"
android:theme="@style/Theme.MyDialog">
<meta-data
android:name="android.app.lib_name"
android:value="" />
</activity>
<activity
android:name=".presentation.review.report.ReportActivity"
android:exported="true">
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.eatssu.android.data.dto.request

data class CheckValidTokenRequest(
val token: String,
)
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.eatssu.android.data.repository

import com.eatssu.android.data.dto.request.CheckValidTokenRequest
import com.eatssu.android.data.dto.request.LoginWithKakaoRequest
import com.eatssu.android.data.dto.response.BaseResponse
import com.eatssu.android.data.dto.response.TokenResponse
Expand All @@ -21,4 +22,9 @@ class OauthRepositoryImpl @Inject constructor(private val oauthService: OauthSer
flow {
emit(oauthService.loginWithKakao(body))
}

override suspend fun checkValidToken(body: CheckValidTokenRequest): Flow<BaseResponse<Boolean>> =
flow {
emit(oauthService.checkValidToken(body))
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.eatssu.android.data.service

import com.eatssu.android.data.dto.request.CheckValidTokenRequest
import com.eatssu.android.data.dto.request.LoginWithKakaoRequest
import com.eatssu.android.data.dto.response.BaseResponse
import com.eatssu.android.data.dto.response.TokenResponse
Expand All @@ -18,4 +19,9 @@ interface OauthService { //여기는 토큰이 없는 레트로핏을 끼웁니
suspend fun loginWithKakao(
@Body request: LoginWithKakaoRequest,
): BaseResponse<TokenResponse>

@POST("oauths/valid/token")
suspend fun checkValidToken(
@Body request: CheckValidTokenRequest,
): BaseResponse<Boolean>
}
11 changes: 6 additions & 5 deletions app/src/main/java/com/eatssu/android/di/NetworkModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,14 @@ object NetworkModule {
val loggingInterceptor = HttpLoggingInterceptor()
loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY)

OkHttpClient.Builder().addInterceptor(loggingInterceptor).addInterceptor(tokenInterceptor)
OkHttpClient.Builder()
.addInterceptor(loggingInterceptor)
.addInterceptor(tokenInterceptor)
.build()
} else {
val loggingInterceptor = HttpLoggingInterceptor()
loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY)

OkHttpClient.Builder().addInterceptor(loggingInterceptor).addInterceptor(tokenInterceptor)
// 프로덕션 환경에서는 로깅 인터셉터를 추가하지 않음
OkHttpClient.Builder()
.addInterceptor(tokenInterceptor)
.build()
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.eatssu.android.domain.repository

import com.eatssu.android.data.dto.request.CheckValidTokenRequest
import com.eatssu.android.data.dto.request.LoginWithKakaoRequest
import com.eatssu.android.data.dto.response.BaseResponse
import com.eatssu.android.data.dto.response.TokenResponse
Expand All @@ -12,5 +13,6 @@ interface OauthRepository {

suspend fun login(body: LoginWithKakaoRequest): Flow<BaseResponse<TokenResponse>>

suspend fun checkValidToken(body: CheckValidTokenRequest): Flow<BaseResponse<Boolean>>
}

Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
package com.eatssu.android.domain.usecase.auth

import com.eatssu.android.data.dto.request.CheckValidTokenRequest
import com.eatssu.android.data.dto.response.BaseResponse
import com.eatssu.android.domain.repository.UserRepository
import com.eatssu.android.domain.repository.OauthRepository
import kotlinx.coroutines.flow.Flow
import javax.inject.Inject

class GetIsAccessTokenValidUseCase @Inject constructor(
private val userRepository: UserRepository,
private val oauthRepository: OauthRepository
) {
suspend operator fun invoke(): Flow<BaseResponse<Boolean>> =
userRepository.checkUserNameValidation("qkqh") //todo api 만들어지면 수정
suspend operator fun invoke(userAccessToken: String): Flow<BaseResponse<Boolean>> =
oauthRepository.checkValidToken(CheckValidTokenRequest(userAccessToken))
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,28 +33,29 @@ class IntroViewModel @Inject constructor(

private fun autoLogin() {
viewModelScope.launch {
_uiState.value = UiState.Loading
val userAccessToken = getAccessTokenUseCase()

_uiState.value = UiState.Loading
try {
// 토큰 존재 여부 확인
if (getAccessTokenUseCase().isEmpty()) {
if (userAccessToken.isEmpty()) {
_uiState.value = UiState.Error
_uiEvent.emit(UiEvent.ShowToast("로그인이 필요합니다"))
return@launch
} else {
checkValid(userAccessToken)
}

checkValid()

} catch (e: Exception) {
_uiState.value = UiState.Error
_uiEvent.emit(UiEvent.ShowToast("오류가 발생했습니다: ${e.message}"))
}
}
}

private fun checkValid() {
private fun checkValid(userAccessToken: String) {
viewModelScope.launch {
getIsAccessTokenValidUseCase()
getIsAccessTokenValidUseCase(userAccessToken)
.collect {
if (it.result == true) { //토큰이 있고 유효함
_uiState.value = UiState.Success(IntroState.ValidToken)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,13 @@ package com.eatssu.android.presentation.login
import android.os.Bundle
import android.view.View
import androidx.activity.viewModels
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import com.eatssu.android.R
import com.eatssu.android.databinding.ActivityLoginBinding
import com.eatssu.android.presentation.UiEvent
import com.eatssu.android.presentation.UiState
import com.eatssu.android.presentation.base.BaseActivity
import com.eatssu.android.presentation.main.MainActivity
import com.eatssu.android.presentation.util.showToast
Expand All @@ -13,7 +18,6 @@ import com.kakao.sdk.common.model.ClientError
import com.kakao.sdk.common.model.ClientErrorCause
import com.kakao.sdk.user.UserApiClient
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
import timber.log.Timber

Expand All @@ -26,73 +30,100 @@ class LoginActivity :

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
initUi()
observeState()
observeEvents()
}

// 툴바 사용하지 않도록 설정
toolbar.let {
toolbar.visibility = View.GONE
toolbarTitle.visibility = View.GONE
setSupportActionBar(it)
supportActionBar?.setDisplayHomeAsUpEnabled(false)
supportActionBar?.setDisplayShowTitleEnabled(false)
private fun initUi() {
// 툴바 숨기기
with(toolbar) {
visibility = View.GONE
setSupportActionBar(this)
supportActionBar?.apply {
setDisplayHomeAsUpEnabled(false)
setDisplayShowTitleEnabled(false)
}
}

setOnClickListener()
binding.ibKakaoLogin.setOnClickListener {
handleKakaoLogin()
}
}


fun setOnClickListener() {
val context = this
binding.mcvKakaoLogin.setOnClickListener {

Timber.d("버튼 클릭")
lifecycleScope.launch {
try {
// 서비스 코드에서는 간단하게 로그인 요청하고 oAuthToken 을 받아올 수 있다.
val oAuthToken = UserApiClient.loginWithKakao(context)
Timber.d("beanbean > $oAuthToken")
postUserInfo()

} catch (error: Throwable) {
if (error is ClientError && error.reason == ClientErrorCause.Cancelled) {
Timber.d("사용자가 명시적으로 취소")
} else {
Timber.e(error, "인증 에러 발생")
}
//kakao login sdk를 통해 유저 정보를 가져와 rest api 호출하는 뷰모델 함수 호출
private fun handleKakaoLogin() {
lifecycleScope.launch {
try {
loginViewModel.setLoadingState()
val oAuthToken = UserApiClient.loginWithKakao(this@LoginActivity)
Timber.d("Kakao login success: $oAuthToken")
UserApiClient.instance.me { user, error ->
user?.let {
val providerID = user.id.toString()
val email = user.kakaoAccount?.email.toString()
loginViewModel.getKakaoLogin(email, providerID)
} ?: Timber.e(error, "User info fetch failed")
}
} catch (error: Throwable) {
handleKakaoLoginError(error)
}
}
}

//kakao login sdk의 error를 다룹니다.
private fun handleKakaoLoginError(error: Throwable) {
when {
error is ClientError && error.reason == ClientErrorCause.Cancelled -> {
Timber.d("User cancelled login")
loginViewModel.setInitState()
}

private fun postUserInfo() {
UserApiClient.instance.me { user, error ->
if (user != null) {
// 유저의 아이디
Timber.d("invoke: id =" + user.id)
val providerID = user.id.toString()
// 유저의 이메일
Timber.d("invoke: email =" + user.kakaoAccount!!.email)
val email = user.kakaoAccount!!.email.toString()

loginViewModel.getLogin(email, providerID)
else -> {
Timber.e(error, "Login failed")
showToast(getString(R.string.login_failed))
}
}
}

lifecycleScope.launch {
loginViewModel.uiState.collectLatest {
if (!it.error && !it.loading) {
Timber.d(it.toString())
showToast(it.toastMessage)
private fun observeState() {
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
loginViewModel.uiState.collect { state ->
when (state) {
is UiState.Loading -> showLoading(true)
is UiState.Success -> {
startActivity<MainActivity>()
finishAffinity()
}
else -> {
showLoading(false)
}
}
}
}
}
}

private fun observeEvents() {
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
loginViewModel.uiEvent.collect { event ->
when (event) {
is UiEvent.ShowToast -> showToast(event.message)
}
}
}
}
}

private fun showLoading(isLoading: Boolean) {
binding.progressBar.visibility = if (isLoading) View.VISIBLE else View.GONE
binding.ibKakaoLogin.visibility = if (isLoading) View.INVISIBLE else View.VISIBLE
}

override fun onBackPressed() {
super.onBackPressed()
finishAffinity()
//탈퇴나 로그아웃 하고 로그인 화면으로 오고, 그 뒤에 뒤로 가기를 눌렀을 때에 백스택 방지
finishAffinity() //로그인 화면에서 뒤로 가기 눌렀을 때에는 백스택 없어야 함 (앱 종료)
}
}
}
Loading