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

Qa/48 카카오톡, 브라우저 모두 미 설치 케이스 대응 #146

Merged
merged 4 commits into from
Feb 13, 2024
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
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,12 @@ package com.susu.feature.loginsignup.login
import com.susu.core.ui.base.SideEffect
import com.susu.core.ui.base.UiState

sealed interface LoginContract {
sealed class LoginEffect : SideEffect {
data object NavigateToReceived : LoginEffect()
data object NavigateToSignUp : LoginEffect()
data class ShowToast(val msg: String) : LoginEffect()
}

data class LoginState(
val isLoading: Boolean = false,
) : UiState
sealed interface LoginEffect : SideEffect {
data object NavigateToReceived : LoginEffect
data object NavigateToSignUp : LoginEffect
data class ShowSnackBar(val message: String) : LoginEffect
}

data class LoginState(
val isLoading: Boolean = false,
) : UiState
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.susu.feature.loginsignup.login

import android.widget.Toast
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.core.MutableTransitionState
import androidx.compose.animation.core.tween
Expand All @@ -24,7 +23,6 @@ import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
Expand All @@ -37,11 +35,16 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.kakao.sdk.common.model.AuthError
import com.kakao.sdk.common.model.AuthErrorCause
import com.kakao.sdk.common.model.ClientError
import com.kakao.sdk.common.model.ClientErrorCause
import com.susu.core.designsystem.component.screen.LoadingScreen
import com.susu.core.designsystem.theme.Gray10
import com.susu.core.designsystem.theme.Gray50
import com.susu.core.designsystem.theme.Orange60
import com.susu.core.designsystem.theme.SusuTheme
import com.susu.core.ui.SnackbarToken
import com.susu.core.ui.SnsProviders
import com.susu.core.ui.extension.susuClickable
import com.susu.feature.loginsignup.R
Expand All @@ -50,11 +53,12 @@ import com.susu.feature.loginsignup.social.KakaoLoginHelper
@Composable
fun LoginRoute(
viewModel: LoginViewModel = hiltViewModel(),
onShowSnackBar: (SnackbarToken) -> Unit,
navigateToReceived: () -> Unit,
navigateToSignUp: () -> Unit,
) {
val context = LocalContext.current
val uiState by viewModel.uiState.collectAsStateWithLifecycle()
val uiState = viewModel.uiState.collectAsStateWithLifecycle().value
val transitionState = remember {
MutableTransitionState(false).apply {
targetState = true
Expand All @@ -64,9 +68,9 @@ fun LoginRoute(
LaunchedEffect(key1 = viewModel.sideEffect) {
viewModel.sideEffect.collect { sideEffect ->
when (sideEffect) {
is LoginContract.LoginEffect.ShowToast -> Toast.makeText(context, sideEffect.msg, Toast.LENGTH_SHORT).show()
LoginContract.LoginEffect.NavigateToReceived -> navigateToReceived()
LoginContract.LoginEffect.NavigateToSignUp -> navigateToSignUp()
is LoginEffect.ShowSnackBar -> onShowSnackBar(SnackbarToken(message = sideEffect.message))
LoginEffect.NavigateToReceived -> navigateToReceived()
LoginEffect.NavigateToSignUp -> navigateToSignUp()
}
}
}
Expand All @@ -78,15 +82,35 @@ fun LoginRoute(
KakaoLoginHelper.login(
context = context,
onSuccess = { viewModel.login(SnsProviders.Kakao, it) },
onFailed = { viewModel.showToast(it) },
onFailed = {
val message = when (it) {
is ClientError -> {
when (it.reason) {
ClientErrorCause.NotSupported -> context.getString(R.string.login_snackbar_kakaotalk_broswer_not_found)
ClientErrorCause.Cancelled -> context.getString(R.string.login_snackbar_login_cancelled)
else -> context.getString(R.string.login_snackbar_unknown_error)
}
}

is AuthError -> {
when (it.reason) {
AuthErrorCause.ServerError -> context.getString(R.string.login_snackbar_kakao_server_error)
else -> context.getString(R.string.login_snackbar_unknown_error)
}
}

else -> context.getString(R.string.login_snackbar_unknown_error)
}
viewModel.showSnackBar(message)
},
)
},
)
}

@Composable
fun LoginScreen(
uiState: LoginContract.LoginState = LoginContract.LoginState(),
uiState: LoginState = LoginState(),
transitionState: MutableTransitionState<Boolean> = MutableTransitionState(true),
onLoginClick: () -> Unit = {},
) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.susu.feature.loginsignup.login

import androidx.lifecycle.viewModelScope
import com.susu.core.model.exception.UnknownException
import com.susu.core.ui.SnsProviders
import com.susu.core.ui.base.BaseViewModel
import com.susu.domain.usecase.loginsignup.CheckCanRegisterUseCase
Expand All @@ -13,30 +14,31 @@ import javax.inject.Inject
class LoginViewModel @Inject constructor(
private val checkCanRegisterUseCase: CheckCanRegisterUseCase,
private val loginUseCase: LoginUseCase,
) : BaseViewModel<LoginContract.LoginState, LoginContract.LoginEffect>(LoginContract.LoginState()) {
) : BaseViewModel<LoginState, LoginEffect>(LoginState()) {

fun login(provider: SnsProviders, oauthAccessToken: String) {
viewModelScope.launch {
intent { copy(isLoading = true) }
// 수수 서버에 가입되지 않은 회원이라면 -> 회원 정보 기입 후 수수 회원가입
checkCanRegisterUseCase(provider = provider.path, oauthAccessToken = oauthAccessToken).onSuccess { canRegister ->
if (canRegister) {
postSideEffect(LoginContract.LoginEffect.NavigateToSignUp)
} else {
loginUseCase(provider = provider.path, oauthAccessToken = oauthAccessToken)
.onSuccess {
postSideEffect(LoginContract.LoginEffect.NavigateToReceived)
}
.onFailure {
postSideEffect(LoginContract.LoginEffect.ShowToast(it.message ?: "수수 로그인에 실패했어요"))
}
checkCanRegisterUseCase(provider = provider.path, oauthAccessToken = oauthAccessToken)
.onSuccess { canRegister ->
if (canRegister) {
postSideEffect(LoginEffect.NavigateToSignUp)
} else {
loginUseCase(provider = provider.path, oauthAccessToken = oauthAccessToken)
.onSuccess {
postSideEffect(LoginEffect.NavigateToReceived)
}
.onFailure {
postSideEffect(LoginEffect.ShowSnackBar(message = it.message ?: UnknownException().message))
}
}
}.onFailure {
postSideEffect(LoginEffect.ShowSnackBar(message = it.message ?: UnknownException().message))
}
}
intent { copy(isLoading = false) }
}
}

fun showToast(error: Throwable?) {
postSideEffect(LoginContract.LoginEffect.ShowToast(error?.message ?: "알 수 없는 에러가 발생했습니다."))
}
fun showSnackBar(message: String) = postSideEffect(LoginEffect.ShowSnackBar(message = message))
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ fun NavGraphBuilder.loginSignupNavGraph(
navigateToLogin: () -> Unit,
navigateToSignUp: () -> Unit,
navigateToReceived: () -> Unit,
onShowToast: (SnackbarToken) -> Unit,
onShowSnackBar: (SnackbarToken) -> Unit,
) {
composable(route = LoginSignupRoute.Parent.Vote.route) {
VoteRoute(
Expand All @@ -31,14 +31,15 @@ fun NavGraphBuilder.loginSignupNavGraph(
LoginRoute(
navigateToReceived = navigateToReceived,
navigateToSignUp = navigateToSignUp,
onShowSnackBar = onShowSnackBar,
)
}
composable(route = LoginSignupRoute.Parent.SignUp.route) {
SignUpRoute(
padding = padding,
navigateToReceived = navigateToReceived,
navigateToLogin = navigateToLogin,
onShowToast = onShowToast,
onShowSnackbar = onShowSnackBar,
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ import com.susu.feature.loginsignup.R
sealed interface SignUpEffect : SideEffect {
data object NavigateToLogin : SignUpEffect
data object NavigateToReceived : SignUpEffect
data class ShowToast(val msg: String) : SignUpEffect
data class ShowSnackbar(val msg: String) : SignUpEffect
data object ShowKakaoErrorSnackbar : SignUpEffect
}

data class SignUpState(
Expand All @@ -20,6 +21,7 @@ data class SignUpState(
val isNameValid: Boolean = true,
val gender: Gender = Gender.NONE,
val birth: Int = -1,
val showDatePicker: Boolean = false,
) : UiState

enum class SignUpStep(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,10 @@ import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
Expand All @@ -42,6 +40,7 @@ import com.susu.core.designsystem.theme.SusuTheme
import com.susu.core.ui.SnackbarToken
import com.susu.core.ui.USER_BIRTH_RANGE
import com.susu.core.ui.extension.collectWithLifecycle
import com.susu.feature.loginsignup.R
import com.susu.feature.loginsignup.signup.content.AdditionalContent
import com.susu.feature.loginsignup.signup.content.NameContent
import com.susu.feature.loginsignup.signup.content.TermsContent
Expand All @@ -54,13 +53,12 @@ fun SignUpRoute(
termViewModel: TermViewModel = hiltViewModel(),
navigateToReceived: () -> Unit,
navigateToLogin: () -> Unit,
onShowToast: (SnackbarToken) -> Unit = {},
onShowSnackbar: (SnackbarToken) -> Unit = {},
) {
val context = LocalContext.current
val uiState: SignUpState by viewModel.uiState.collectAsStateWithLifecycle()
val termState: TermState by termViewModel.uiState.collectAsStateWithLifecycle()

var showDatePicker by remember { mutableStateOf(false) }

BackHandler {
viewModel.goPreviousStep()
}
Expand All @@ -69,7 +67,12 @@ fun SignUpRoute(
when (sideEffect) {
SignUpEffect.NavigateToLogin -> navigateToLogin()
SignUpEffect.NavigateToReceived -> navigateToReceived()
is SignUpEffect.ShowToast -> onShowToast(SnackbarToken(message = sideEffect.msg))
is SignUpEffect.ShowSnackbar -> onShowSnackbar(SnackbarToken(message = sideEffect.msg))
SignUpEffect.ShowKakaoErrorSnackbar -> onShowSnackbar(
SnackbarToken(
message = context.getString(R.string.signup_snackbar_kakao_login_error),
),
)
}
}

Expand Down Expand Up @@ -151,7 +154,7 @@ fun SignUpRoute(
selectedGender = uiState.gender,
selectedYear = uiState.birth,
onGenderSelect = viewModel::updateGender,
onYearClick = { showDatePicker = true },
onYearClick = viewModel::showDatePicker,
)
}

Expand All @@ -169,14 +172,14 @@ fun SignUpRoute(
}
}

if (showDatePicker) {
if (uiState.showDatePicker) {
SusuYearPickerBottomSheet(
yearRange = USER_BIRTH_RANGE,
reverseItemOrder = true,
maximumContainerHeight = 322.dp,
onDismissRequest = {
viewModel.updateBirth(it)
showDatePicker = false
viewModel.hideDatePicker()
},
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.susu.feature.loginsignup.signup

import androidx.lifecycle.viewModelScope
import com.susu.core.model.SignUpUser
import com.susu.core.model.exception.UnknownException
import com.susu.core.ui.Gender
import com.susu.core.ui.SnsProviders
import com.susu.core.ui.USER_NAME_MAX_LENGTH
Expand All @@ -18,6 +19,9 @@ class SignUpViewModel @Inject constructor(
private val signUpUseCase: SignUpUseCase,
) : BaseViewModel<SignUpState, SignUpEffect>(SignUpState()) {

fun showDatePicker() = intent { copy(showDatePicker = true) }
fun hideDatePicker() = intent { copy(showDatePicker = false) }

fun updateName(name: String) {
val trimmedName = name.trim()
if (trimmedName.length > USER_NAME_MAX_LENGTH) return
Expand Down Expand Up @@ -92,10 +96,10 @@ class SignUpViewModel @Inject constructor(
).onSuccess {
postSideEffect(SignUpEffect.NavigateToReceived)
}.onFailure {
postSideEffect(SignUpEffect.ShowToast(it.message ?: "에러 발생"))
postSideEffect(SignUpEffect.ShowSnackbar(it.message ?: UnknownException().message))
}
} else {
postSideEffect(SignUpEffect.ShowToast("카카오톡 로그인 에러 발생"))
postSideEffect(SignUpEffect.ShowKakaoErrorSnackbar)
}
intent { copy(isLoading = false) }
}
Expand Down
5 changes: 5 additions & 0 deletions feature/loginsignup/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,9 @@
<string name="signup_term_agree">동의하기</string>
<string name="signup_name_description">반가워요!\n이름을 알려주세요</string>
<string name="signup_additional_description">아래 정보들을 알려주시면\n통계를 알려드릴 수 있어요</string>
<string name="login_snackbar_kakaotalk_broswer_not_found">카카오톡 또는 브라우저를 설치해주세요</string>
<string name="login_snackbar_login_cancelled">로그인을 취소했습니다</string>
<string name="login_snackbar_unknown_error">알 수 없는 에러가 발생했어요</string>
<string name="login_snackbar_kakao_server_error">카카오톡 서버에서 에러가 발생했어요</string>
<string name="signup_snackbar_kakao_login_error">카카오톡 로그인 에러가 발생했어요</string>
</resources>
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ internal fun MainScreen(
navigateToReceived = navigator::navigateSent,
navigateToLogin = navigator::navigateLogin,
navigateToSignUp = navigator::navigateSignup,
onShowToast = viewModel::onShowSnackbar,
onShowSnackBar = viewModel::onShowSnackbar,
padding = innerPadding,
)

Expand Down
Loading