diff --git a/app/src/main/java/pokitmons/pokit/navigation/RootNavHost.kt b/app/src/main/java/pokitmons/pokit/navigation/RootNavHost.kt index 5ae07935..f5d95f1d 100644 --- a/app/src/main/java/pokitmons/pokit/navigation/RootNavHost.kt +++ b/app/src/main/java/pokitmons/pokit/navigation/RootNavHost.kt @@ -45,7 +45,8 @@ fun RootNavHost( val viewModel: LoginViewModel = hiltViewModel() LoginScreen( loginViewModel = viewModel, - onNavigateToTermsOfServiceScreen = { navHostController.navigate(TermOfService.route) } + onNavigateToTermsOfServiceScreen = { navHostController.navigate(TermOfService.route) }, + onNavigateToHomeScreen = { navHostController.navigate(Home.route) } ) } diff --git a/data/src/main/java/pokitmons/pokit/data/datasource/local/TokenManager.kt b/data/src/main/java/pokitmons/pokit/data/datasource/local/TokenManager.kt index 368cfe92..26a6e3c4 100644 --- a/data/src/main/java/pokitmons/pokit/data/datasource/local/TokenManager.kt +++ b/data/src/main/java/pokitmons/pokit/data/datasource/local/TokenManager.kt @@ -13,6 +13,7 @@ class TokenManager @Inject constructor( companion object { val ACCESS_TOKEN = stringPreferencesKey("access_token") val REFRESH_TOKEN = stringPreferencesKey("refresh_token") + val AUTH_TYPE = stringPreferencesKey("auth_type") } fun getAccessToken(): Flow { @@ -21,6 +22,18 @@ class TokenManager @Inject constructor( } } + suspend fun setAuthType(type: String) { + dataStore.edit { prefs -> + prefs[AUTH_TYPE] = type + } + } + + fun getAuthType(): Flow { + return dataStore.data.map { prefs -> + prefs[ACCESS_TOKEN] ?: "" + } + } + suspend fun saveAccessToken(token: String) { dataStore.edit { prefs -> prefs[ACCESS_TOKEN] = token diff --git a/data/src/main/java/pokitmons/pokit/data/mapper/auth/AuthMapper.kt b/data/src/main/java/pokitmons/pokit/data/mapper/auth/AuthMapper.kt index 9a528c28..ebee74f7 100644 --- a/data/src/main/java/pokitmons/pokit/data/mapper/auth/AuthMapper.kt +++ b/data/src/main/java/pokitmons/pokit/data/mapper/auth/AuthMapper.kt @@ -11,7 +11,8 @@ object AuthMapper { fun mapperToSNSLogin(snsLoginResponse: SNSLoginResponse): SNSLoginResult { return SNSLoginResult( accessToken = snsLoginResponse.accessToken, - refreshToken = snsLoginResponse.refreshToken + refreshToken = snsLoginResponse.refreshToken, + isRegistered = snsLoginResponse.isRegistered ) } diff --git a/data/src/main/java/pokitmons/pokit/data/model/auth/response/SNSLoginResponse.kt b/data/src/main/java/pokitmons/pokit/data/model/auth/response/SNSLoginResponse.kt index 64d57407..963f69a7 100644 --- a/data/src/main/java/pokitmons/pokit/data/model/auth/response/SNSLoginResponse.kt +++ b/data/src/main/java/pokitmons/pokit/data/model/auth/response/SNSLoginResponse.kt @@ -6,4 +6,5 @@ import kotlinx.serialization.Serializable data class SNSLoginResponse( val accessToken: String, val refreshToken: String, + val isRegistered: Boolean, ) diff --git a/data/src/main/java/pokitmons/pokit/data/repository/auth/AuthRepositoryImpl.kt b/data/src/main/java/pokitmons/pokit/data/repository/auth/AuthRepositoryImpl.kt index aa3f8245..72a9b1ec 100644 --- a/data/src/main/java/pokitmons/pokit/data/repository/auth/AuthRepositoryImpl.kt +++ b/data/src/main/java/pokitmons/pokit/data/repository/auth/AuthRepositoryImpl.kt @@ -1,5 +1,6 @@ package pokitmons.pokit.data.repository.auth +import kotlinx.coroutines.flow.Flow import pokitmons.pokit.data.datasource.local.TokenManager import pokitmons.pokit.data.datasource.remote.auth.AuthDataSource import pokitmons.pokit.data.mapper.auth.AuthMapper @@ -60,4 +61,12 @@ class AuthRepositoryImpl @Inject constructor( override suspend fun setRefreshToken(token: String) { tokenManager.saveRefreshToken(token) } + + override suspend fun setAuthType(type: String) { + tokenManager.setAuthType(type) + } + + override suspend fun getAuthType(): Flow { + return tokenManager.getAuthType() + } } diff --git a/domain/src/main/java/pokitmons/pokit/domain/model/auth/SNSLoginResult.kt b/domain/src/main/java/pokitmons/pokit/domain/model/auth/SNSLoginResult.kt index 79bd155a..84da23db 100644 --- a/domain/src/main/java/pokitmons/pokit/domain/model/auth/SNSLoginResult.kt +++ b/domain/src/main/java/pokitmons/pokit/domain/model/auth/SNSLoginResult.kt @@ -3,4 +3,5 @@ package pokitmons.pokit.domain.model.auth data class SNSLoginResult( val accessToken: String, val refreshToken: String, + val isRegistered: Boolean, ) diff --git a/domain/src/main/java/pokitmons/pokit/domain/repository/auth/AuthRepository.kt b/domain/src/main/java/pokitmons/pokit/domain/repository/auth/AuthRepository.kt index ab6c63cc..5190f9c8 100644 --- a/domain/src/main/java/pokitmons/pokit/domain/repository/auth/AuthRepository.kt +++ b/domain/src/main/java/pokitmons/pokit/domain/repository/auth/AuthRepository.kt @@ -1,5 +1,6 @@ package pokitmons.pokit.domain.repository.auth +import kotlinx.coroutines.flow.Flow import pokitmons.pokit.domain.commom.PokitResult import pokitmons.pokit.domain.model.auth.DuplicateNicknameResult import pokitmons.pokit.domain.model.auth.SNSLoginResult @@ -11,4 +12,8 @@ interface AuthRepository { suspend fun signUp(nickname: String, categories: List): PokitResult suspend fun setAccessToken(token: String) suspend fun setRefreshToken(token: String) + + // TODO 리팩토링 + suspend fun setAuthType(type: String) + suspend fun getAuthType(): Flow } diff --git a/domain/src/main/java/pokitmons/pokit/domain/usecase/auth/TokenUseCase.kt b/domain/src/main/java/pokitmons/pokit/domain/usecase/auth/TokenUseCase.kt index df6bb0c5..e64399c6 100644 --- a/domain/src/main/java/pokitmons/pokit/domain/usecase/auth/TokenUseCase.kt +++ b/domain/src/main/java/pokitmons/pokit/domain/usecase/auth/TokenUseCase.kt @@ -1,5 +1,6 @@ package pokitmons.pokit.domain.usecase.auth +import kotlinx.coroutines.flow.Flow import pokitmons.pokit.domain.repository.auth.AuthRepository import javax.inject.Inject @@ -11,4 +12,12 @@ class TokenUseCase @Inject constructor(private val authRepository: AuthRepositor suspend fun setRefreshToken(token: String) { authRepository.setRefreshToken(token) } + + suspend fun setAuthType(type: String) { + authRepository.setAuthType(type) + } + + suspend fun getAuthType(): Flow { + return authRepository.getAuthType() + } } diff --git a/feature/login/src/main/java/pokitmons/pokit/LoginState.kt b/feature/login/src/main/java/pokitmons/pokit/LoginState.kt index 8dd741ce..6c85bad9 100644 --- a/feature/login/src/main/java/pokitmons/pokit/LoginState.kt +++ b/feature/login/src/main/java/pokitmons/pokit/LoginState.kt @@ -5,6 +5,8 @@ import pokitmons.pokit.domain.commom.PokitError sealed class LoginState { data object Init : LoginState() data object Login : LoginState() + data object Registered : LoginState() + data object AutoLogin : LoginState() data class Failed(val error: PokitError) : LoginState() } diff --git a/feature/login/src/main/java/pokitmons/pokit/LoginViewModel.kt b/feature/login/src/main/java/pokitmons/pokit/LoginViewModel.kt index bcb4b1fa..8fda76d2 100644 --- a/feature/login/src/main/java/pokitmons/pokit/LoginViewModel.kt +++ b/feature/login/src/main/java/pokitmons/pokit/LoginViewModel.kt @@ -11,6 +11,7 @@ import kotlinx.coroutines.delay import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import pokitmons.pokit.domain.commom.PokitResult @@ -31,6 +32,13 @@ class LoginViewModel @Inject constructor( private val signUpUseCase: SignUpUseCase, private val tokenUseCase: TokenUseCase, ) : ViewModel() { + init { + viewModelScope.launch { + if (tokenUseCase.getAuthType().first() == "구글") { + _loginState.emit(LoginState.AutoLogin) + } + } + } private var duplicateNicknameJob: Job? = null private val _loginState: MutableStateFlow = MutableStateFlow(LoginState.Init) @@ -48,6 +56,8 @@ class LoginViewModel @Inject constructor( private val _categories = mutableStateListOf() val categories: List get() = _categories + private var authType = "" + fun inputText(inputNickname: String) { _inputNicknameState.update { duplicateNicknameState -> duplicateNicknameState.copy(nickname = inputNickname) @@ -63,12 +73,27 @@ class LoginViewModel @Inject constructor( when (loginResult) { is PokitResult.Success -> { - tokenUseCase.apply { - setAccessToken(loginResult.result.accessToken) - setRefreshToken(loginResult.result.refreshToken) + authType = authPlatform + when (loginResult.result.isRegistered) { + true -> { + tokenUseCase.apply { + setAccessToken(loginResult.result.accessToken) + setRefreshToken(loginResult.result.refreshToken) + setAuthType(authType) + } + _loginState.emit(LoginState.Registered) + } + + false -> { + tokenUseCase.apply { + setAccessToken(loginResult.result.accessToken) + setRefreshToken(loginResult.result.refreshToken) + } + _loginState.emit(LoginState.Login) + } } - _loginState.emit(LoginState.Login) } + is PokitResult.Error -> _loginState.emit(LoginState.Failed(loginResult.error)) } } @@ -84,8 +109,14 @@ class LoginViewModel @Inject constructor( .map { categoryState -> categoryState.name } ) ) { - is PokitResult.Success -> { _signUpState.emit(SignUpState.SignUp) } - is PokitResult.Error -> { _signUpState.emit(SignUpState.Failed(signUpResult.error)) } + is PokitResult.Success -> { + tokenUseCase.setAuthType(authType) + _signUpState.emit(SignUpState.SignUp) + } + + is PokitResult.Error -> { + _signUpState.emit(SignUpState.Failed(signUpResult.error)) + } } } } @@ -100,6 +131,7 @@ class LoginViewModel @Inject constructor( duplicateNicknameState.copy(isDuplicate = duplicateNicknameResult.result.isDuplicate) } } + is PokitResult.Error -> {} } } diff --git a/feature/login/src/main/java/pokitmons/pokit/login/LoginScreen.kt b/feature/login/src/main/java/pokitmons/pokit/login/LoginScreen.kt index b5150432..56948277 100644 --- a/feature/login/src/main/java/pokitmons/pokit/login/LoginScreen.kt +++ b/feature/login/src/main/java/pokitmons/pokit/login/LoginScreen.kt @@ -14,7 +14,6 @@ import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.rememberCoroutineScope @@ -32,24 +31,19 @@ import com.google.firebase.auth.AuthResult import com.google.firebase.auth.FirebaseAuth import com.google.firebase.auth.OAuthProvider import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.flowOn -import kotlinx.coroutines.flow.launchIn -import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch import pokitmons.pokit.LoginState import pokitmons.pokit.LoginViewModel import pokitmons.pokit.core.ui.components.atom.button.attributes.PokitLoginButtonType import pokitmons.pokit.core.ui.components.atom.loginbutton.PokitLoginButton import pokitmons.pokit.core.ui.theme.PokitTheme -import kotlin.coroutines.CoroutineContext -import kotlin.coroutines.EmptyCoroutineContext @SuppressLint("CoroutineCreationDuringComposition") @Composable fun LoginScreen( loginViewModel: LoginViewModel, onNavigateToTermsOfServiceScreen: () -> Unit, + onNavigateToHomeScreen: () -> Unit, ) { val loginState by loginViewModel.loginState.collectAsState() val context: Context = LocalContext.current @@ -61,10 +55,17 @@ fun LoginScreen( loginViewModel.changeState() onNavigateToTermsOfServiceScreen() } + is LoginState.Registered -> { + loginViewModel.changeState() + onNavigateToHomeScreen() + } is LoginState.Failed -> { // TODO 로그인 실패 바텀시트 렌더링 Toast.makeText(context, (loginState as LoginState.Failed).error.toString(), Toast.LENGTH_SHORT).show() } + is LoginState.AutoLogin -> { + onNavigateToHomeScreen() + } } // Column 자체가 가운데로 오게 하려면? @@ -201,14 +202,3 @@ private fun handleAuthResult( } } } - -@SuppressLint("ComposableNaming") -@Composable -fun Flow.collectAsEffect( - context: CoroutineContext = EmptyCoroutineContext, - block: (T) -> Unit, -) { - LaunchedEffect(Unit) { - onEach(block).flowOn(context).launchIn(this) - } -}