diff --git a/app/build.gradle.kts b/app/build.gradle.kts index a822d410..9823163f 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -18,7 +18,7 @@ android { applicationId = "co.kr.tnt" minSdk = 27 targetSdk = 35 - versionCode = 2 + versionCode = 3 versionName = "0.0.1" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" diff --git a/core/login/src/main/java/co/kr/tnt/login/kakao/KakaoLoginSdk.kt b/core/login/src/main/java/co/kr/tnt/login/kakao/KakaoLoginSdk.kt index d6840f36..60d75060 100644 --- a/core/login/src/main/java/co/kr/tnt/login/kakao/KakaoLoginSdk.kt +++ b/core/login/src/main/java/co/kr/tnt/login/kakao/KakaoLoginSdk.kt @@ -6,6 +6,7 @@ import co.kr.tnt.login.LoginException.AuthException import co.kr.tnt.login.LoginException.CancelException import co.kr.tnt.login.LoginSdk import com.kakao.sdk.auth.model.OAuthToken +import com.kakao.sdk.common.model.AuthError import com.kakao.sdk.common.model.ClientError import com.kakao.sdk.common.model.ClientErrorCause import com.kakao.sdk.user.UserApiClient @@ -42,7 +43,18 @@ class KakaoLoginSdk @Inject constructor() : LoginSdk { if (userApiClient.isKakaoTalkLoginAvailable(context)) { // 카카오톡 로그인 - userApiClient.loginWithKakaoTalk(context, callback = callback) + userApiClient.loginWithKakaoTalk( + context, + callback = callback@{ oAuthToken, throwable -> + // 카카오톡이 설치되어 있으나 로그인되어 있지 않은 경우 대응 + if (throwable is AuthError && throwable.statusCode == 302) { + userApiClient.loginWithKakaoAccount(context, callback = callback) + return@callback + } + + callback(oAuthToken, throwable) + }, + ) } else { // 카카오톡 웹 로그인 userApiClient.loginWithKakaoAccount(context, callback = callback) diff --git a/core/navigation/src/main/java/co/kr/tnt/navigation/RouteModel.kt b/core/navigation/src/main/java/co/kr/tnt/navigation/RouteModel.kt index 68ce7151..d9177a69 100644 --- a/core/navigation/src/main/java/co/kr/tnt/navigation/RouteModel.kt +++ b/core/navigation/src/main/java/co/kr/tnt/navigation/RouteModel.kt @@ -19,6 +19,7 @@ sealed interface Route { val authId: String, val authType: String, val email: String, + val messagingToken: String, ) : Route @Serializable @@ -26,6 +27,7 @@ sealed interface Route { val authId: String, val authType: String, val email: String, + val messagingToken: String, ) : Route @Serializable @@ -33,6 +35,7 @@ sealed interface Route { val authId: String, val authType: String, val email: String, + val messagingToken: String, ) : Route @Serializable diff --git a/data/repository/src/main/java/co/kr/data/repository/SignUpRepositoryImpl.kt b/data/repository/src/main/java/co/kr/data/repository/SignUpRepositoryImpl.kt index 3f848d7c..fd79678b 100644 --- a/data/repository/src/main/java/co/kr/data/repository/SignUpRepositoryImpl.kt +++ b/data/repository/src/main/java/co/kr/data/repository/SignUpRepositoryImpl.kt @@ -31,18 +31,18 @@ internal class SignUpRepositoryImpl @Inject constructor( socialId: String, socialType: String, email: String, + messagingToken: String, ): SignUpResult { val profileImagePart = profileImage?.let { val requestFile = it.asRequestBody("image/*".toMediaTypeOrNull()) MultipartBody.Part.createFormData("profileImage", it.name, requestFile) } - // TODO FCM token val signUpRequest = user.toSignUpRequest( socialId = socialId, socialType = socialType, email = email, - fcmToken = "EMPTY", + fcmToken = messagingToken, ) val requestBody = signUpRequest.toRequestBody() diff --git a/domain/src/main/java/co/kr/tnt/domain/repository/SignUpRepository.kt b/domain/src/main/java/co/kr/tnt/domain/repository/SignUpRepository.kt index 22aa679e..1c4b19ad 100644 --- a/domain/src/main/java/co/kr/tnt/domain/repository/SignUpRepository.kt +++ b/domain/src/main/java/co/kr/tnt/domain/repository/SignUpRepository.kt @@ -11,5 +11,6 @@ interface SignUpRepository { socialId: String, socialType: String, email: String, + messagingToken: String, ): SignUpResult } diff --git a/feature/login/src/main/java/co/kr/tnt/login/LoginContract.kt b/feature/login/src/main/java/co/kr/tnt/login/LoginContract.kt index 0c4c678e..2bad615e 100644 --- a/feature/login/src/main/java/co/kr/tnt/login/LoginContract.kt +++ b/feature/login/src/main/java/co/kr/tnt/login/LoginContract.kt @@ -37,6 +37,9 @@ internal class LoginContract { data class ShowToast(val message: String) : LoginSideEffect data class NavigateToWebView(val url: String) : LoginSideEffect data class NavigateToHome(val userType: UserType) : LoginSideEffect - data class NavigateToSignup(val loginResult: LoginResult) : LoginSideEffect + data class NavigateToSignup( + val loginResult: LoginResult, + val messagingToken: String, + ) : LoginSideEffect } } diff --git a/feature/login/src/main/java/co/kr/tnt/login/LoginScreen.kt b/feature/login/src/main/java/co/kr/tnt/login/LoginScreen.kt index ae79eac4..f56cfacf 100644 --- a/feature/login/src/main/java/co/kr/tnt/login/LoginScreen.kt +++ b/feature/login/src/main/java/co/kr/tnt/login/LoginScreen.kt @@ -1,5 +1,6 @@ package co.kr.tnt.login +import android.util.Log import androidx.compose.foundation.Image import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement @@ -65,7 +66,7 @@ internal fun LoginRoute( viewModel: LoginViewModel = hiltViewModel(), navigateToWebView: (url: String) -> Unit, navigateToHome: (UserType) -> Unit, - navigateToSignup: (LoginResult) -> Unit, + navigateToSignup: (loginResult: LoginResult, messagingToken: String) -> Unit, ) { val context = LocalContext.current val snackbar = LocalSnackbar.current @@ -91,6 +92,7 @@ internal fun LoginRoute( ) } .onFailure { throwable -> + Log.e("TnT Login error", throwable.toString()) viewModel.setEvent(LoginUiEvent.OnAuthFail(throwable)) } } @@ -137,7 +139,7 @@ internal fun LoginRoute( is LoginSideEffect.NavigateToSignup -> { showBottomSheet = false - navigateToSignup(effect.loginResult) + navigateToSignup(effect.loginResult, effect.messagingToken) } } } diff --git a/feature/login/src/main/java/co/kr/tnt/login/LoginViewModel.kt b/feature/login/src/main/java/co/kr/tnt/login/LoginViewModel.kt index ca2b9e06..2729bace 100644 --- a/feature/login/src/main/java/co/kr/tnt/login/LoginViewModel.kt +++ b/feature/login/src/main/java/co/kr/tnt/login/LoginViewModel.kt @@ -103,7 +103,7 @@ internal class LoginViewModel @Inject constructor( private fun navigateToSignup() { loginResult?.let { loginResult -> - sendEffect(LoginSideEffect.NavigateToSignup(loginResult)) + sendEffect(LoginSideEffect.NavigateToSignup(loginResult, messagingToken)) this@LoginViewModel.loginResult = null } ?: run { sendEffect(LoginSideEffect.ShowToast("로그인에 실패하였습니다. 다시 시도해주세요.")) diff --git a/feature/login/src/main/java/co/kr/tnt/login/navigation/LoginNavigation.kt b/feature/login/src/main/java/co/kr/tnt/login/navigation/LoginNavigation.kt index c6a9d6b9..a26597a6 100644 --- a/feature/login/src/main/java/co/kr/tnt/login/navigation/LoginNavigation.kt +++ b/feature/login/src/main/java/co/kr/tnt/login/navigation/LoginNavigation.kt @@ -26,7 +26,7 @@ fun NavController.navigateToLogin( fun NavGraphBuilder.loginScreen( navigateToWebView: (url: String) -> Unit, navigateToHome: (UserType) -> Unit, - navigateToSignup: (LoginResult) -> Unit, + navigateToSignup: (loginResult: LoginResult, messagingToken: String) -> Unit, ) { composable { LoginRoute( diff --git a/feature/main/src/main/java/co/kr/tnt/main/ui/TnTNavHost.kt b/feature/main/src/main/java/co/kr/tnt/main/ui/TnTNavHost.kt index 015f6e29..2790e07b 100644 --- a/feature/main/src/main/java/co/kr/tnt/main/ui/TnTNavHost.kt +++ b/feature/main/src/main/java/co/kr/tnt/main/ui/TnTNavHost.kt @@ -54,11 +54,12 @@ fun TnTNavHost( UserType.TRAINEE -> navController.navigateToTraineeMain(clearBackStack = true) } }, - navigateToSignup = { loginResult -> + navigateToSignup = { loginResult, messagingToken -> navController.navigateToRoleSelection( authId = loginResult.authId, authType = loginResult.authType.name, email = loginResult.email, + messagingToken = messagingToken, ) }, ) diff --git a/feature/roleselect/src/main/java/co/kr/tnt/roleselect/RoleSelectionNavigation.kt b/feature/roleselect/src/main/java/co/kr/tnt/roleselect/RoleSelectionNavigation.kt index 192c5867..f91ad3a4 100644 --- a/feature/roleselect/src/main/java/co/kr/tnt/roleselect/RoleSelectionNavigation.kt +++ b/feature/roleselect/src/main/java/co/kr/tnt/roleselect/RoleSelectionNavigation.kt @@ -11,25 +11,27 @@ fun NavController.navigateToRoleSelection( authId: String, authType: String, email: String, + messagingToken: String, navOptions: NavOptionsBuilder.() -> Unit = {}, ) = navigate( route = Route.RoleSelection( authId = authId, authType = authType, email = email, + messagingToken = messagingToken, ), builder = navOptions, ) fun NavGraphBuilder.roleSelectionScreen( - navigateToTraineeSignUp: (authId: String, authType: String, email: String) -> Unit, - navigateToTrainerSignUp: (authId: String, authType: String, email: String) -> Unit, + navigateToTraineeSignUp: (authId: String, authType: String, email: String, messagingToken: String) -> Unit, + navigateToTrainerSignUp: (authId: String, authType: String, email: String, messagingToken: String) -> Unit, ) { composable { navBackstackEntry -> navBackstackEntry.toRoute().apply { RoleSelectionRoute( - navigateToTraineeSignUp = { navigateToTraineeSignUp(authId, authType, email) }, - navigateToTrainerSignUp = { navigateToTrainerSignUp(authId, authType, email) }, + navigateToTraineeSignUp = { navigateToTraineeSignUp(authId, authType, email, messagingToken) }, + navigateToTrainerSignUp = { navigateToTrainerSignUp(authId, authType, email, messagingToken) }, ) } } diff --git a/feature/trainee/signup/src/main/java/co/kr/tnt/trainee/signup/TraineeSignUpContract.kt b/feature/trainee/signup/src/main/java/co/kr/tnt/trainee/signup/TraineeSignUpContract.kt index 0a978836..b89ee334 100644 --- a/feature/trainee/signup/src/main/java/co/kr/tnt/trainee/signup/TraineeSignUpContract.kt +++ b/feature/trainee/signup/src/main/java/co/kr/tnt/trainee/signup/TraineeSignUpContract.kt @@ -72,6 +72,7 @@ internal class TraineeSignUpContract { val id: String, val email: String, val authType: String, + val messagingToken: String, ) : TraineeSignUpUiEvent } diff --git a/feature/trainee/signup/src/main/java/co/kr/tnt/trainee/signup/TraineeSignUpScreen.kt b/feature/trainee/signup/src/main/java/co/kr/tnt/trainee/signup/TraineeSignUpScreen.kt index 09440f0a..d13782cf 100644 --- a/feature/trainee/signup/src/main/java/co/kr/tnt/trainee/signup/TraineeSignUpScreen.kt +++ b/feature/trainee/signup/src/main/java/co/kr/tnt/trainee/signup/TraineeSignUpScreen.kt @@ -19,6 +19,7 @@ internal fun TraineeSignUpRoute( authId: String, authType: String, email: String, + messagingToken: String, navigateToPrevious: () -> Unit, navigateToConnect: () -> Unit, viewModel: TraineeSignUpViewModel = hiltViewModel(), @@ -46,6 +47,7 @@ internal fun TraineeSignUpRoute( id = authId, email = email, authType = authType, + messagingToken = messagingToken, ), ) }, diff --git a/feature/trainee/signup/src/main/java/co/kr/tnt/trainee/signup/TraineeSignUpViewModel.kt b/feature/trainee/signup/src/main/java/co/kr/tnt/trainee/signup/TraineeSignUpViewModel.kt index 2e42986e..39739d57 100644 --- a/feature/trainee/signup/src/main/java/co/kr/tnt/trainee/signup/TraineeSignUpViewModel.kt +++ b/feature/trainee/signup/src/main/java/co/kr/tnt/trainee/signup/TraineeSignUpViewModel.kt @@ -43,6 +43,7 @@ internal class TraineeSignUpViewModel @Inject constructor( id = event.id, email = event.email, authType = event.authType, + messagingToken = event.messagingToken, ) } } @@ -53,6 +54,7 @@ internal class TraineeSignUpViewModel @Inject constructor( id: String, email: String, authType: String, + messagingToken: String, ) { viewModelScope.launch { updateState { copy(isLoading = true) } @@ -83,6 +85,7 @@ internal class TraineeSignUpViewModel @Inject constructor( socialId = id, socialType = authType, email = email, + messagingToken = messagingToken, ) }.onSuccess { sendEffect(TraineeSignUpEffect.NavigateToConnect) diff --git a/feature/trainee/signup/src/main/java/co/kr/tnt/trainee/signup/navigation/TraineeSignUpNavigation.kt b/feature/trainee/signup/src/main/java/co/kr/tnt/trainee/signup/navigation/TraineeSignUpNavigation.kt index 94750d5e..6a3cfdcb 100644 --- a/feature/trainee/signup/src/main/java/co/kr/tnt/trainee/signup/navigation/TraineeSignUpNavigation.kt +++ b/feature/trainee/signup/src/main/java/co/kr/tnt/trainee/signup/navigation/TraineeSignUpNavigation.kt @@ -12,12 +12,14 @@ fun NavController.navigateToTraineeSignUp( authId: String, authType: String, email: String, + messagingToken: String, navOptions: NavOptionsBuilder.() -> Unit = {}, ) = navigate( route = Route.TraineeSignUp( authId = authId, authType = authType, email = email, + messagingToken = messagingToken, ), builder = navOptions, ) @@ -32,6 +34,7 @@ fun NavGraphBuilder.traineeSignUpScreen( authId = authId, authType = authType, email = email, + messagingToken = messagingToken, navigateToPrevious = navigateToPrevious, navigateToConnect = navigateToConnect, ) diff --git a/feature/trainer/signup/src/main/java/co/kr/tnt/trainer/signup/TrainerSignUpContract.kt b/feature/trainer/signup/src/main/java/co/kr/tnt/trainer/signup/TrainerSignUpContract.kt index 4a854edb..c5cc62fb 100644 --- a/feature/trainer/signup/src/main/java/co/kr/tnt/trainer/signup/TrainerSignUpContract.kt +++ b/feature/trainer/signup/src/main/java/co/kr/tnt/trainer/signup/TrainerSignUpContract.kt @@ -33,6 +33,7 @@ internal class TrainerSignUpContract { val id: String, val email: String, val authType: String, + val messagingToken: String, ) : TrainerSignUpUiEvent } diff --git a/feature/trainer/signup/src/main/java/co/kr/tnt/trainer/signup/TrainerSignUpScreen.kt b/feature/trainer/signup/src/main/java/co/kr/tnt/trainer/signup/TrainerSignUpScreen.kt index 99159da3..949668bc 100644 --- a/feature/trainer/signup/src/main/java/co/kr/tnt/trainer/signup/TrainerSignUpScreen.kt +++ b/feature/trainer/signup/src/main/java/co/kr/tnt/trainer/signup/TrainerSignUpScreen.kt @@ -17,6 +17,7 @@ internal fun TrainerSignUpRoute( authId: String, authType: String, email: String, + messagingToken: String, navigateToPrevious: () -> Unit, navigateToInvite: (ScreenMode) -> Unit, viewModel: TrainerSignUpViewModel = hiltViewModel(), @@ -39,6 +40,7 @@ internal fun TrainerSignUpRoute( id = authId, email = email, authType = authType, + messagingToken = messagingToken, ), ) }, diff --git a/feature/trainer/signup/src/main/java/co/kr/tnt/trainer/signup/TrainerSignUpViewModel.kt b/feature/trainer/signup/src/main/java/co/kr/tnt/trainer/signup/TrainerSignUpViewModel.kt index 9e89fbee..34267fa8 100644 --- a/feature/trainer/signup/src/main/java/co/kr/tnt/trainer/signup/TrainerSignUpViewModel.kt +++ b/feature/trainer/signup/src/main/java/co/kr/tnt/trainer/signup/TrainerSignUpViewModel.kt @@ -39,6 +39,7 @@ internal class TrainerSignUpViewModel @Inject constructor( id = event.id, email = event.email, authType = event.authType, + messagingToken = event.messagingToken, ) } } @@ -49,6 +50,7 @@ internal class TrainerSignUpViewModel @Inject constructor( id: String, email: String, authType: String, + messagingToken: String, ) { viewModelScope.launch(Dispatchers.IO) { updateState { copy(isLoading = true) } @@ -73,6 +75,7 @@ internal class TrainerSignUpViewModel @Inject constructor( socialId = id, socialType = authType, email = email, + messagingToken = messagingToken, ) }.onSuccess { sendEffect(TrainerSignUpEffect.NavigateToConnect) diff --git a/feature/trainer/signup/src/main/java/co/kr/tnt/trainer/signup/navigation/TrainerSignUpNavigation.kt b/feature/trainer/signup/src/main/java/co/kr/tnt/trainer/signup/navigation/TrainerSignUpNavigation.kt index 813985d6..30cf668f 100644 --- a/feature/trainer/signup/src/main/java/co/kr/tnt/trainer/signup/navigation/TrainerSignUpNavigation.kt +++ b/feature/trainer/signup/src/main/java/co/kr/tnt/trainer/signup/navigation/TrainerSignUpNavigation.kt @@ -13,12 +13,14 @@ fun NavController.navigateToTrainerSignUp( authId: String, authType: String, email: String, + messagingToken: String, navOptions: NavOptionsBuilder.() -> Unit = {}, ) = navigate( route = Route.TrainerSignUp( authId = authId, authType = authType, email = email, + messagingToken = messagingToken, ), builder = navOptions, ) @@ -33,6 +35,7 @@ fun NavGraphBuilder.trainerSignUpScreen( authId = authId, authType = authType, email = email, + messagingToken = messagingToken, navigateToPrevious = navigateToPrevious, navigateToInvite = navigateToInvite, )