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

[FIX/#300,#302] Domain 레이어 Paging3 제거 & FlowWithLifecycle 적용 #304

Merged
merged 20 commits into from
Oct 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
da4b141
[FIX/#302] 타임라인 뷰 Paging Repository 제거
Marchbreeze Oct 15, 2023
24dff9c
[FIX/#302] 프로필 flowWithLifecycle 적용
Marchbreeze Oct 15, 2023
c7934c8
[FIX/#302] 추천친구 flowWithLifecycle 적용
Marchbreeze Oct 15, 2023
5bc8ef4
[FIX/#302] 결제 flowWithLifecycle 적용
Marchbreeze Oct 15, 2023
eadfa38
[FIX/#302] 타임라인 뷰 flowWithLifecycle 적용
Marchbreeze Oct 15, 2023
f499543
[FIX/#302] 검색 뷰 flowWithLifecycle 적용
Marchbreeze Oct 15, 2023
52ce691
[FIX/#302] 온보딩 친구추가 뷰 flowWithLifecycle 적용
Marchbreeze Oct 15, 2023
6fe8431
[FIX/#302] 로그인 뷰 flowWithLifecycle 적용
Marchbreeze Oct 15, 2023
5d5fbe1
[FIX/#302] 친구동의 뷰 flowWithLifecycle 적용
Marchbreeze Oct 15, 2023
742187a
[FIX/#302] BillingManager 함수화 수정
Marchbreeze Oct 15, 2023
3e5d302
Merge branch 'develop' of https://github.com/team-yello/YELLO-Android…
Marchbreeze Oct 15, 2023
e3a1e6b
[FIX/#302] 로그인 뷰 flow 검증
Marchbreeze Oct 17, 2023
f650378
[FIX/#302] 온보딩 친구추가 flow 검증
Marchbreeze Oct 17, 2023
3592911
[FIX/#302] 프로필, 타임라인 flow 검증
Marchbreeze Oct 17, 2023
07f5a0b
[FIX/#302] 추천친구 flow 검증
Marchbreeze Oct 17, 2023
585b215
[FIX/#302] 검색 flow 검증
Marchbreeze Oct 17, 2023
1d71ee8
[FIX/#302] 결제 flow 검증
Marchbreeze Oct 17, 2023
7c2692e
[FIX/#302] 프로필 뷰 아이디 @ 고정 해제
Marchbreeze Oct 17, 2023
d201cba
[FIX/#302] 결제 flow 검증
Marchbreeze Oct 17, 2023
527b1b0
Merge branch 'develop' of https://github.com/team-yello/YELLO-Android…
Marchbreeze Oct 18, 2023
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
7 changes: 0 additions & 7 deletions app/src/main/java/com/el/yello/di/RepositoryModule.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package com.el.yello.di

import com.example.data.repository.AuthRepositoryImpl
import com.example.data.repository.LookRepositoryImpl
import com.example.data.repository.OnboardingRepositoryImpl
import com.example.data.repository.PayRepositoryImpl
import com.example.data.repository.ProfileRepositoryImpl
Expand All @@ -10,7 +9,6 @@ import com.example.data.repository.SearchRepositoryImpl
import com.example.data.repository.VoteRepositoryImpl
import com.example.data.repository.YelloRepositoryImpl
import com.example.domain.repository.AuthRepository
import com.example.domain.repository.LookRepository
import com.example.domain.repository.OnboardingRepository
import com.example.domain.repository.PayRepository
import com.example.domain.repository.ProfileRepository
Expand Down Expand Up @@ -67,9 +65,4 @@ object RepositoryModule {
fun providePayRepository(payRepositoryImpl: PayRepositoryImpl): PayRepository =
payRepositoryImpl

@Provides
@Singleton
fun provideLookRepository(lookRepositoryImpl: LookRepositoryImpl): LookRepository =
lookRepositoryImpl

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package com.el.yello.presentation.auth
import android.content.Intent
import android.os.Bundle
import androidx.activity.viewModels
import androidx.lifecycle.flowWithLifecycle
import androidx.lifecycle.lifecycleScope
import com.el.yello.R
import com.el.yello.databinding.ActivitySignInBinding
import com.el.yello.presentation.auth.SignInViewModel.Companion.FRIEND_LIST
Expand All @@ -17,17 +19,19 @@ import com.example.ui.context.toast
import com.example.ui.view.UiState
import com.example.ui.view.setOnSingleClickListener
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach

@AndroidEntryPoint
class SignInActivity : BindingActivity<ActivitySignInBinding>(R.layout.activity_sign_in) {

private val viewModel by viewModels<SignInViewModel>()

private var userKakaoId: Long = 0
private var userName: String = ""
private var userGender: String = ""
private var userEmail: String = ""
private var userImage: String = ""
private var userName: String = String()
private var userGender: String = String()
private var userEmail: String = String()
private var userImage: String = String()
Comment on lines +31 to +34
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

똑같이 빈 문자열로 초기화될 것 같은데 이렇게 바꾼 이유가 있나요?
별 이유 없다면 먼가 "" 요게 더 직관적으로 빈 문자열이라고 이해될 것 같은 늑김...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

코드에서 ""처럼 초록색 스트링값 안봤으면 해서 추출하는 느낌으로 전환해봤서요..!


override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Expand All @@ -52,21 +56,21 @@ class SignInActivity : BindingActivity<ActivitySignInBinding>(R.layout.activity_
}

private fun observeDeviceTokenError() {
viewModel.getDeviceTokenError.observe(this) {
toast(getString(R.string.sign_in_error_connection))
}
viewModel.getDeviceTokenError.flowWithLifecycle(lifecycle).onEach { error ->
if (error) toast(getString(R.string.sign_in_error_connection))
}.launchIn(lifecycleScope)
}

// 카카오통 앱 로그인에 실패한 경우 웹 로그인 시도
private fun observeAppLoginError() {
viewModel.isAppLoginAvailable.observe(this) { available ->
viewModel.isAppLoginAvailable.flowWithLifecycle(lifecycle).onEach { available ->
if (!available) viewModel.startKakaoLogIn(this)
}
}.launchIn(lifecycleScope)
Comment on lines +59 to +68
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

코드 스타일마다 다를 것 같긴 하지만... 지금 SignIn에 상태 관련된 변수가 많아서 sealed class 하나로 합쳐서 분기 처리하면 더 깔끔할 수도 있지 않을까 하는 생각이 들었습니다!

}

// 서비스 토큰 교체 서버 통신 결과에 따라서 분기 처리 진행
private fun observeChangeTokenState() {
viewModel.postChangeTokenState.observe(this) { state ->
viewModel.postChangeTokenState.flowWithLifecycle(lifecycle).onEach { state ->
when (state) {
is UiState.Success -> {
// 200(가입된 아이디): 온보딩 뷰 생략하고 바로 메인 화면으로 이동 위해 유저 정보 받기
Expand All @@ -78,21 +82,21 @@ class SignInActivity : BindingActivity<ActivitySignInBinding>(R.layout.activity_
// 403, 404 : 온보딩 뷰로 이동 위해 카카오 유저 정보 얻기
viewModel.getKakaoInfo()
} else {
// 401 : 에러 발생
// 나머지 : 에러 발생
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

83번째 줄에 viewModel.getKakaoInfo()를 호출하는 로직은 UI와 관련 없는 비즈니스 로직이라 뷰모델에서 처리하는 게 더 구조에 적합하지 않을까여?
뷰에서는 이런 로직이 보이지 않는 게 더 유지보수하기 좋을 것 같습니다!

toast(getString(R.string.sign_in_error_connection))
}
}

is UiState.Loading -> {}
is UiState.Loading -> return@onEach

is UiState.Empty -> {}
is UiState.Empty -> return@onEach
}
}
}.launchIn(lifecycleScope)
}

// Failure -> 카카오에 등록된 유저 정보 받아온 후 친구목록 동의 화면으로 이동
private fun observeKakaoUserInfoState() {
viewModel.getKakaoInfoState.observe(this) { state ->
viewModel.getKakaoInfoState.flowWithLifecycle(lifecycle).onEach { state ->
when (state) {
is UiState.Success -> {
userKakaoId = state.data?.id ?: 0
Expand All @@ -103,19 +107,17 @@ class SignInActivity : BindingActivity<ActivitySignInBinding>(R.layout.activity_
viewModel.checkFriendsListValid()
}

is UiState.Failure -> {
yelloSnackbar(binding.root, getString(R.string.msg_error))
}
is UiState.Failure -> yelloSnackbar(binding.root, getString(R.string.msg_error))

is UiState.Empty -> {}
is UiState.Empty -> return@onEach

is UiState.Loading -> {}
is UiState.Loading -> return@onEach
}
}
}.launchIn(lifecycleScope)
}

private fun observeFriendsListValidState() {
viewModel.getKakaoValidState.observe(this) { state ->
viewModel.getKakaoValidState.flowWithLifecycle(lifecycle).onEach { state ->
when (state) {
is UiState.Success -> {
val friendScope = state.data.find { it.id == FRIEND_LIST }
Expand All @@ -126,18 +128,18 @@ class SignInActivity : BindingActivity<ActivitySignInBinding>(R.layout.activity_
}
}

is UiState.Failure -> {
yelloSnackbar(binding.root, getString(R.string.msg_error))
}
is UiState.Empty -> {}
is UiState.Loading -> {}
is UiState.Failure -> yelloSnackbar(binding.root, getString(R.string.msg_error))

is UiState.Empty -> return@onEach

is UiState.Loading -> return@onEach
}
}
}.launchIn(lifecycleScope)
}

// Success -> 서버에 등록된 유저 정보가 있는지 확인 후 메인 액티비티로 이동
private fun observeUserDataState() {
viewModel.getUserProfileState.observe(this) { state ->
viewModel.getUserProfileState.flowWithLifecycle(lifecycle).onEach { state ->
when (state) {
is UiState.Success -> {
if (viewModel.getIsFirstLoginData()) {
Expand All @@ -151,17 +153,21 @@ class SignInActivity : BindingActivity<ActivitySignInBinding>(R.layout.activity_
}
}

is UiState.Failure -> {
yelloSnackbar(binding.root, getString(R.string.msg_error))
}
is UiState.Failure -> yelloSnackbar(binding.root, getString(R.string.msg_error))

is UiState.Empty -> {
yelloSnackbar(binding.root, getString(R.string.msg_error))
}
is UiState.Empty -> return@onEach

is UiState.Loading -> {}
is UiState.Loading -> return@onEach
}
}.launchIn(lifecycleScope)
}

private fun startMainActivity() {
Intent(this, MainActivity::class.java).apply {
addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
startActivity(this)
}
finish()
}

private fun startSocialSyncActivity() {
Expand Down Expand Up @@ -191,14 +197,6 @@ class SignInActivity : BindingActivity<ActivitySignInBinding>(R.layout.activity_
addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
}

private fun startMainActivity() {
Intent(this, MainActivity::class.java).apply {
addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
startActivity(this)
}
finish()
}

companion object {
const val EXTRA_KAKAO_ID = "KAKAO_ID"
const val EXTRA_EMAIL = "KAKAO_EMAIL"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
package com.el.yello.presentation.auth

import android.content.Context
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.el.yello.presentation.auth.SignInActivity.Companion.CODE_NOT_SIGNED_IN
import com.el.yello.presentation.auth.SignInActivity.Companion.CODE_NO_UUID
import com.example.domain.entity.AuthTokenRequestModel
import com.example.domain.entity.AuthTokenModel
import com.example.domain.entity.AuthTokenRequestModel
import com.example.domain.entity.ProfileUserModel
import com.example.domain.repository.AuthRepository
import com.example.domain.repository.OnboardingRepository
import com.example.domain.repository.ProfileRepository
Expand All @@ -21,6 +20,8 @@ import com.kakao.sdk.user.UserApiClient
import com.kakao.sdk.user.model.Scope
import com.kakao.sdk.user.model.User
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch
import retrofit2.HttpException
import javax.inject.Inject
Expand All @@ -32,27 +33,27 @@ class SignInViewModel @Inject constructor(
private val profileRepository: ProfileRepository
) : ViewModel() {

private val _postChangeTokenState = MutableLiveData<UiState<AuthTokenModel?>>()
val postChangeTokenState: LiveData<UiState<AuthTokenModel?>> = _postChangeTokenState
private val _postChangeTokenState = MutableStateFlow<UiState<AuthTokenModel>>(UiState.Empty)
val postChangeTokenState: StateFlow<UiState<AuthTokenModel?>> = _postChangeTokenState

private val _getUserProfileState = MutableLiveData<UiState<Unit>>()
val getUserProfileState: LiveData<UiState<Unit>> = _getUserProfileState
private val _getUserProfileState = MutableStateFlow<UiState<ProfileUserModel>>(UiState.Empty)
val getUserProfileState: StateFlow<UiState<ProfileUserModel>> = _getUserProfileState

private val _getKakaoInfoState = MutableLiveData<UiState<User?>>()
val getKakaoInfoState: LiveData<UiState<User?>> = _getKakaoInfoState
private val _getKakaoInfoState = MutableStateFlow<UiState<User>>(UiState.Empty)
val getKakaoInfoState: StateFlow<UiState<User?>> = _getKakaoInfoState

private val _getKakaoValidState = MutableLiveData<UiState<List<Scope>>>()
val getKakaoValidState: LiveData<UiState<List<Scope>>> = _getKakaoValidState
private val _getKakaoValidState = MutableStateFlow<UiState<List<Scope>>>(UiState.Empty)
val getKakaoValidState: StateFlow<UiState<List<Scope>>> = _getKakaoValidState

private val serviceTermsList = listOf(THUMBNAIL, EMAIL, FRIEND_LIST, NAME, GENDER)

private var deviceToken = String()

private val _getDeviceTokenError = MutableLiveData<String>()
val getDeviceTokenError: LiveData<String> = _getDeviceTokenError
private val _getDeviceTokenError = MutableStateFlow(false)
val getDeviceTokenError: StateFlow<Boolean> = _getDeviceTokenError
Comment on lines +52 to +53
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Boolean 값을 저장하는 변수인데 조금 더 명확하게 네이밍해주는 건 어떨까요?!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

와 이 링크 미쳐따


private val _isAppLoginAvailable = MutableLiveData<Boolean>()
val isAppLoginAvailable: LiveData<Boolean> = _isAppLoginAvailable
private val _isAppLoginAvailable = MutableStateFlow(true)
val isAppLoginAvailable: StateFlow<Boolean> = _isAppLoginAvailable

var isResigned = false
private set
Expand Down Expand Up @@ -82,10 +83,11 @@ class SignInViewModel @Inject constructor(

fun initLoginState() {
_isAppLoginAvailable.value = true
_getDeviceTokenError.value = false
}

fun startKakaoLogIn(context: Context) {
if (UserApiClient.instance.isKakaoTalkLoginAvailable(context) && isAppLoginAvailable.value == true) {
if (UserApiClient.instance.isKakaoTalkLoginAvailable(context) && isAppLoginAvailable.value) {
UserApiClient.instance.loginWithKakaoTalk(
context = context,
callback = appLoginCallback,
Expand Down Expand Up @@ -117,11 +119,14 @@ class SignInViewModel @Inject constructor(

fun checkFriendsListValid() {
val scopes = mutableListOf(FRIEND_LIST)
UserApiClient.instance.scopes(scopes) { scopeInfo, error->
_getKakaoValidState.value = UiState.Loading
UserApiClient.instance.scopes(scopes) { scopeInfo, error ->
if (error != null) {
_getKakaoValidState.value = UiState.Failure(error.message.toString())
} else if (scopeInfo != null) {
_getKakaoValidState.value = UiState.Success(scopeInfo.scopes ?: listOf())
} else {
_getKakaoValidState.value = UiState.Failure(ERROR)
}
}
}
Expand All @@ -132,8 +137,8 @@ class SignInViewModel @Inject constructor(
social: String = KAKAO,
deviceToken: String
) {
_postChangeTokenState.value = UiState.Loading
viewModelScope.launch {
_postChangeTokenState.value = UiState.Loading
onboardingRepository.postTokenToServiceToken(
AuthTokenRequestModel(accessToken, social, deviceToken),
)
Expand All @@ -159,15 +164,14 @@ class SignInViewModel @Inject constructor(

// 서버통신 - (가입되어 있는) 유저 정보 가져오기
fun getUserDataFromServer() {
_getUserProfileState.value = UiState.Loading
viewModelScope.launch {
profileRepository.getUserData()
.onSuccess { profile ->
if (profile == null) {
_getUserProfileState.value = UiState.Empty
return@launch
if (profile != null) {
_getUserProfileState.value = UiState.Success(profile)
authRepository.setYelloId(profile.yelloId)
}
_getUserProfileState.value = UiState.Success(Unit)
authRepository.setYelloId(profile.yelloId)
}
.onFailure { t ->
if (t is HttpException) {
Expand All @@ -184,14 +188,12 @@ class SignInViewModel @Inject constructor(
deviceToken = task.result
authRepository.setDeviceToken(deviceToken)
} else {
_getDeviceTokenError.value = task.result
_getDeviceTokenError.value = true
}
}
}

fun getIsFirstLoginData(): Boolean {
return authRepository.getIsFirstLoginData()
}
fun getIsFirstLoginData() = authRepository.getIsFirstLoginData()

companion object {
const val KAKAO = "KAKAO"
Expand Down
Loading