diff --git a/feature/src/main/AndroidManifest.xml b/feature/src/main/AndroidManifest.xml
index 75bf52d..214feab 100644
--- a/feature/src/main/AndroidManifest.xml
+++ b/feature/src/main/AndroidManifest.xml
@@ -9,7 +9,7 @@
android:supportsRtl="true"
android:theme="@style/Theme.NOWSOPTAndroid">
@@ -17,13 +17,6 @@
-
-
\ No newline at end of file
diff --git a/feature/src/main/java/com/sopt/now/feature/MainActivity.kt b/feature/src/main/java/com/sopt/now/feature/MainActivity.kt
index c922a13..047ec3b 100644
--- a/feature/src/main/java/com/sopt/now/feature/MainActivity.kt
+++ b/feature/src/main/java/com/sopt/now/feature/MainActivity.kt
@@ -1,10 +1,15 @@
package com.sopt.now.feature
+import android.util.Log
+import android.view.MotionEvent
import android.view.View
+import android.view.inputmethod.InputMethodManager
import androidx.activity.OnBackPressedCallback
+import androidx.activity.viewModels
import androidx.lifecycle.flowWithLifecycle
import androidx.lifecycle.lifecycleScope
import androidx.navigation.NavController
+import androidx.navigation.Navigation
import androidx.navigation.fragment.NavHostFragment
import androidx.navigation.fragment.findNavController
import androidx.navigation.ui.setupWithNavController
@@ -23,9 +28,12 @@ class MainActivity : BindingActivity(R.layout.activity_main
private var backPressedTime = 0L
private val backPressedFlow = MutableSharedFlow()
+ private val viewModel: MainViewModel by viewModels()
+
override fun initView() {
initMainBottomNavigation()
initBackDoublePressed()
+ observeAutoLogin()
}
private fun initMainBottomNavigation() {
@@ -33,6 +41,7 @@ class MainActivity : BindingActivity(R.layout.activity_main
(supportFragmentManager.findFragmentById(R.id.fcv_home) as NavHostFragment)
.findNavController()
binding.bnvHome.setupWithNavController(navController)
+ navController.navigate(R.id.fragment_login)
doubleBackPressedOnHomeTab(navController)
setBottomNavigationVisibility(navController)
}
@@ -82,4 +91,47 @@ class MainActivity : BindingActivity(R.layout.activity_main
snackBar(binding.root, getString(R.string.main_back_once_pressed_exit))
}
}
+
+ private fun observeAutoLogin() {
+ viewModel.autoLoginState.flowWithLifecycle(lifecycle).onEach { isAutoLogin ->
+ val navController = Navigation.findNavController(this, R.id.fcv_home)
+ when (isAutoLogin) {
+ true -> navController.navigate(R.id.fragment_home)
+ false -> navController.navigate(R.id.fragment_login)
+ }
+ }.launchIn(lifecycleScope)
+ }
+
+ override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
+ val imm: InputMethodManager =
+ getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
+ imm.hideSoftInputFromWindow(currentFocus?.windowToken, 0)
+ return super.dispatchTouchEvent(ev)
+ }
+
+ override fun onResume() {
+ super.onResume()
+
+ logFragmentStack()
+ }
+
+ private fun logFragmentStack() {
+ val fragmentManager =
+ supportFragmentManager.findFragmentById(R.id.fcv_home) as NavHostFragment
+
+ fragmentManager.childFragmentManager.addOnBackStackChangedListener {
+ if (fragmentManager.childFragmentManager.backStackEntryCount == 0) {
+ Log.i(
+ "backstack",
+ fragmentManager.childFragmentManager.backStackEntryCount.toString()
+ )
+
+ } else {
+ Log.i(
+ "backstack",
+ fragmentManager.childFragmentManager.backStackEntryCount.toString()
+ )
+ }
+ }
+ }
}
diff --git a/feature/src/main/java/com/sopt/now/feature/MainViewModel.kt b/feature/src/main/java/com/sopt/now/feature/MainViewModel.kt
new file mode 100644
index 0000000..83d4361
--- /dev/null
+++ b/feature/src/main/java/com/sopt/now/feature/MainViewModel.kt
@@ -0,0 +1,31 @@
+package com.sopt.now.feature
+
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewModelScope
+import com.sopt.now.domain.usecase.sharedprefusecase.GetCheckLoginUseCase
+import dagger.hilt.android.lifecycle.HiltViewModel
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.asStateFlow
+import kotlinx.coroutines.launch
+import javax.inject.Inject
+
+@HiltViewModel
+class MainViewModel @Inject constructor(
+ private val getCheckLoginUseCase: GetCheckLoginUseCase,
+) : ViewModel() {
+ private val _autoLoginState = MutableStateFlow(false)
+ val autoLoginState: StateFlow get() = _autoLoginState.asStateFlow()
+
+ init {
+ checkAutoLogin()
+ }
+
+ private fun checkAutoLogin() {
+ viewModelScope.launch {
+ _autoLoginState.value = isAutoLogin()
+ }
+ }
+
+ private fun isAutoLogin(): Boolean = getCheckLoginUseCase.invoke()
+}
\ No newline at end of file
diff --git a/feature/src/main/java/com/sopt/now/feature/auth/LoginActivity.kt b/feature/src/main/java/com/sopt/now/feature/auth/LoginActivity.kt
deleted file mode 100644
index f119526..0000000
--- a/feature/src/main/java/com/sopt/now/feature/auth/LoginActivity.kt
+++ /dev/null
@@ -1,101 +0,0 @@
-package com.sopt.now.feature.auth
-
-import android.content.Intent
-import android.view.MotionEvent
-import android.view.inputmethod.InputMethodManager
-import androidx.activity.result.ActivityResultLauncher
-import androidx.activity.result.contract.ActivityResultContracts
-import androidx.activity.viewModels
-import androidx.lifecycle.flowWithLifecycle
-import androidx.lifecycle.lifecycleScope
-import com.sopt.now.core.base.BindingActivity
-import com.sopt.now.core.util.context.snackBar
-import com.sopt.now.core.util.context.toast
-import com.sopt.now.core.util.intent.getSafeParcelable
-import com.sopt.now.core.util.intent.navigateTo
-import com.sopt.now.core.view.UiState
-import com.sopt.now.feature.MainActivity
-import com.sopt.now.feature.R
-import com.sopt.now.feature.databinding.ActivityLoginBinding
-import com.sopt.now.feature.model.User
-import com.sopt.now.feature.util.KeyStorage
-import dagger.hilt.android.AndroidEntryPoint
-import kotlinx.coroutines.flow.launchIn
-import kotlinx.coroutines.flow.onEach
-
-@AndroidEntryPoint
-class LoginActivity : BindingActivity(R.layout.activity_login) {
- private lateinit var resultLauncher: ActivityResultLauncher
- private val viewModel by viewModels()
-
- override fun initView() {
- initAutoLoginStateObserve()
- initRegisterResultLauncher()
- initBtnClickListener()
- initSignUpStateObserve()
- }
-
- private fun initAutoLoginStateObserve() {
- viewModel.autoLoginState.flowWithLifecycle(lifecycle).onEach { isAutoLogin ->
- when (isAutoLogin) {
- true -> navigateTo(this@LoginActivity)
- false -> return@onEach
- }
- }.launchIn(lifecycleScope)
- }
-
- private fun initRegisterResultLauncher() {
- resultLauncher =
- registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
- if (result.resultCode == RESULT_OK) {
- result.data?.getSafeParcelable(name = KeyStorage.USER_INPUT)
- ?.let { receivedUserInput ->
- viewModel.setSavedUserInfo(receivedUserInput.toUserEntity())
- }
- }
- }
- }
-
- private fun initBtnClickListener() {
- initLoginBtnClickListener()
- initSignUpBtnClickListener()
- }
-
- private fun initLoginBtnClickListener() = with(binding) {
- btnLogin.setOnClickListener {
- viewModel.setLogin(
- id = etLoginId.text.toString(),
- pwd = etLoginPwd.text.toString()
- )
- }
- }
-
- private fun initSignUpBtnClickListener() {
- binding.tvLoginSignUp.setOnClickListener {
- val intent = Intent(this@LoginActivity, SignUpActivity::class.java)
- resultLauncher.launch(intent)
- }
- }
-
- private fun initSignUpStateObserve() {
- viewModel.loginState.flowWithLifecycle(lifecycle).onEach { state ->
- when (state) {
- is UiState.Success -> {
- toast(getString(R.string.login_completed, getString(R.string.login)))
- viewModel.saveCheckLoginSharedPreference(true)
- navigateTo(this)
- }
-
- is UiState.Failure -> snackBar(binding.root, state.errorMessage)
- else -> Unit
- }
- }.launchIn(lifecycleScope)
- }
-
- override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
- val imm: InputMethodManager =
- getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
- imm.hideSoftInputFromWindow(currentFocus?.windowToken, 0)
- return super.dispatchTouchEvent(ev)
- }
-}
diff --git a/feature/src/main/java/com/sopt/now/feature/auth/LoginFragment.kt b/feature/src/main/java/com/sopt/now/feature/auth/LoginFragment.kt
new file mode 100644
index 0000000..c80701e
--- /dev/null
+++ b/feature/src/main/java/com/sopt/now/feature/auth/LoginFragment.kt
@@ -0,0 +1,64 @@
+package com.sopt.now.feature.auth
+
+import androidx.fragment.app.viewModels
+import androidx.lifecycle.flowWithLifecycle
+import androidx.lifecycle.lifecycleScope
+import androidx.navigation.NavOptions
+import androidx.navigation.fragment.findNavController
+import com.sopt.now.core.base.BindingFragment
+import com.sopt.now.core.util.fragment.snackBar
+import com.sopt.now.core.util.fragment.toast
+import com.sopt.now.core.view.UiState
+import com.sopt.now.feature.R
+import com.sopt.now.feature.databinding.FragmentLoginBinding
+import dagger.hilt.android.AndroidEntryPoint
+import kotlinx.coroutines.flow.launchIn
+import kotlinx.coroutines.flow.onEach
+
+@AndroidEntryPoint
+class LoginFragment : BindingFragment(R.layout.fragment_login) {
+ private val viewModel by viewModels()
+
+ override fun initView() {
+ initBtnClickListener()
+ initSignUpStateObserve()
+ }
+
+ private fun initBtnClickListener() {
+ initLoginBtnClickListener()
+ initSignUpBtnClickListener()
+ }
+
+ private fun initLoginBtnClickListener() = with(binding) {
+ btnLogin.setOnClickListener {
+ viewModel.setLogin(
+ id = etLoginId.text.toString(),
+ pwd = etLoginPwd.text.toString()
+ )
+ }
+ }
+
+ private fun initSignUpBtnClickListener() {
+ binding.tvLoginSignUp.setOnClickListener {
+ findNavController().navigate(R.id.fragment_sign_up)
+ }
+ }
+
+ private fun initSignUpStateObserve() {
+ viewModel.loginState.flowWithLifecycle(lifecycle).onEach { state ->
+ when (state) {
+ is UiState.Success -> {
+ toast(getString(R.string.login_completed, getString(R.string.login)))
+ viewModel.saveCheckLoginSharedPreference(true)
+ val navOptions = NavOptions.Builder()
+ .setPopUpTo(R.id.nav_graph, true)
+ .build()
+ findNavController().navigate(R.id.fragment_home, null, navOptions)
+ }
+
+ is UiState.Failure -> snackBar(binding.root, state.errorMessage)
+ else -> Unit
+ }
+ }.launchIn(lifecycleScope)
+ }
+}
diff --git a/feature/src/main/java/com/sopt/now/feature/auth/LoginViewModel.kt b/feature/src/main/java/com/sopt/now/feature/auth/LoginViewModel.kt
index c2dd1a4..d4bb0ca 100644
--- a/feature/src/main/java/com/sopt/now/feature/auth/LoginViewModel.kt
+++ b/feature/src/main/java/com/sopt/now/feature/auth/LoginViewModel.kt
@@ -2,27 +2,24 @@ package com.sopt.now.feature.auth
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
-import com.sopt.now.feature.util.StringResources
import com.sopt.now.core.view.UiState
import com.sopt.now.domain.entity.UserEntity
-import com.sopt.now.domain.usecase.sharedprefusecase.GetCheckLoginUseCase
import com.sopt.now.domain.usecase.sharedprefusecase.GetUserInfoUseCase
import com.sopt.now.domain.usecase.sharedprefusecase.SaveCheckLoginUseCase
+import com.sopt.now.feature.util.StringResources
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asSharedFlow
-import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
import javax.inject.Inject
@HiltViewModel
class LoginViewModel @Inject constructor(
private val getUserInfoUseCase: GetUserInfoUseCase,
- private val getCheckLoginUseCase: GetCheckLoginUseCase,
- private val saveCheckLoginUseCase: SaveCheckLoginUseCase
+ private val saveCheckLoginUseCase: SaveCheckLoginUseCase,
) : ViewModel() {
private val _savedUserInfo = MutableStateFlow(
UserEntity(
@@ -37,32 +34,21 @@ class LoginViewModel @Inject constructor(
private val _loginState = MutableSharedFlow>()
val loginState: SharedFlow> get() = _loginState.asSharedFlow()
- private val _autoLoginState = MutableStateFlow(false)
- val autoLoginState: StateFlow get() = _autoLoginState.asStateFlow()
-
init {
- checkAutoLogin()
+ getUserInfo()
}
- private fun checkAutoLogin() {
+ private fun getUserInfo() {
viewModelScope.launch {
- _autoLoginState.value = isAutoLogin()
- if (!isAutoLogin()) {
- _savedUserInfo.value = getUserInfoUseCase.invoke()
- }
+ _savedUserInfo.value = getUserInfoUseCase.invoke()
+
}
}
- private fun isAutoLogin(): Boolean = getCheckLoginUseCase.invoke()
-
fun saveCheckLoginSharedPreference(input: Boolean) {
saveCheckLoginUseCase.invoke(input)
}
- fun setSavedUserInfo(input: UserEntity) {
- _savedUserInfo.value = input
- }
-
fun setLogin(id: String, pwd: String) {
checkLoginValidate(id, pwd)
}
diff --git a/feature/src/main/java/com/sopt/now/feature/auth/SignUpActivity.kt b/feature/src/main/java/com/sopt/now/feature/auth/SignUpFragment.kt
similarity index 60%
rename from feature/src/main/java/com/sopt/now/feature/auth/SignUpActivity.kt
rename to feature/src/main/java/com/sopt/now/feature/auth/SignUpFragment.kt
index 479b558..236e0a5 100644
--- a/feature/src/main/java/com/sopt/now/feature/auth/SignUpActivity.kt
+++ b/feature/src/main/java/com/sopt/now/feature/auth/SignUpFragment.kt
@@ -1,25 +1,22 @@
package com.sopt.now.feature.auth
-import android.content.Intent
-import android.view.MotionEvent
-import android.view.inputmethod.InputMethodManager
-import androidx.activity.viewModels
+import androidx.fragment.app.viewModels
import androidx.lifecycle.flowWithLifecycle
import androidx.lifecycle.lifecycleScope
-import com.sopt.now.core.base.BindingActivity
-import com.sopt.now.core.util.context.snackBar
-import com.sopt.now.core.util.context.toast
+import androidx.navigation.fragment.findNavController
+import com.sopt.now.core.base.BindingFragment
+import com.sopt.now.core.util.fragment.snackBar
+import com.sopt.now.core.util.fragment.toast
import com.sopt.now.core.view.UiState
import com.sopt.now.feature.R
-import com.sopt.now.feature.databinding.ActivitySignUpBinding
+import com.sopt.now.feature.databinding.FragmentSignUpBinding
import com.sopt.now.feature.model.User
-import com.sopt.now.feature.util.KeyStorage
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
@AndroidEntryPoint
-class SignUpActivity : BindingActivity(R.layout.activity_sign_up) {
+class SignUpFragment : BindingFragment(R.layout.fragment_sign_up) {
private val viewModel by viewModels()
override fun initView() {
@@ -50,7 +47,7 @@ class SignUpActivity : BindingActivity(R.layout.activity_
is UiState.Success -> {
toast(getString(R.string.login_completed, getString(R.string.sign_up)))
viewModel.saveUserInfoSharedPreference(state.data.toUserEntity())
- navigateToLoginActivity(state.data)
+ findNavController().navigate(R.id.fragment_login)
}
is UiState.Failure -> {
@@ -62,19 +59,4 @@ class SignUpActivity : BindingActivity(R.layout.activity_
}.launchIn(lifecycleScope)
}
- private fun navigateToLoginActivity(userInputData: User) {
- Intent().apply {
- putExtra(KeyStorage.USER_INPUT, userInputData)
- }.also {
- setResult(RESULT_OK, it)
- finish()
- }
- }
-
- override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
- val imm: InputMethodManager =
- getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
- imm.hideSoftInputFromWindow(currentFocus?.windowToken, 0)
- return super.dispatchTouchEvent(ev)
- }
}
diff --git a/feature/src/main/java/com/sopt/now/feature/mypage/MyPageFragment.kt b/feature/src/main/java/com/sopt/now/feature/mypage/MyPageFragment.kt
index fdeb08f..df94e6e 100644
--- a/feature/src/main/java/com/sopt/now/feature/mypage/MyPageFragment.kt
+++ b/feature/src/main/java/com/sopt/now/feature/mypage/MyPageFragment.kt
@@ -1,11 +1,11 @@
package com.sopt.now.feature.mypage
import androidx.fragment.app.viewModels
+import androidx.navigation.NavOptions
+import androidx.navigation.fragment.findNavController
import com.sopt.now.core.base.BindingFragment
import com.sopt.now.core.util.fragment.toast
-import com.sopt.now.core.util.intent.navigateTo
import com.sopt.now.feature.R
-import com.sopt.now.feature.auth.LoginActivity
import com.sopt.now.feature.databinding.FragmentMyPageBinding
import dagger.hilt.android.AndroidEntryPoint
@@ -26,7 +26,12 @@ class MyPageFragment : BindingFragment(R.layout.fragment_
binding.tvMainSignOut.setOnClickListener {
viewModel.updateCheckLoginState(false)
toast(getString(R.string.login_completed, getString(R.string.main_logout_under_bar)))
- navigateTo(requireContext())
+
+ val navOptions = NavOptions.Builder()
+ .setPopUpTo(R.id.nav_graph, true)
+ .build()
+
+ findNavController().navigate(R.id.fragment_login, null, navOptions)
}
}
@@ -39,7 +44,11 @@ class MyPageFragment : BindingFragment(R.layout.fragment_
getString(R.string.main_clear_user_under_bar)
)
)
- navigateTo(requireContext())
+
+ val navOptions = NavOptions.Builder()
+ .setPopUpTo(R.id.nav_graph, true)
+ .build()
+ findNavController().navigate(R.id.fragment_login, null, navOptions)
}
}
diff --git a/feature/src/main/res/layout/activity_login.xml b/feature/src/main/res/layout/fragment_login.xml
similarity index 100%
rename from feature/src/main/res/layout/activity_login.xml
rename to feature/src/main/res/layout/fragment_login.xml
diff --git a/feature/src/main/res/layout/activity_sign_up.xml b/feature/src/main/res/layout/fragment_sign_up.xml
similarity index 100%
rename from feature/src/main/res/layout/activity_sign_up.xml
rename to feature/src/main/res/layout/fragment_sign_up.xml
diff --git a/feature/src/main/res/navigation/nav_graph.xml b/feature/src/main/res/navigation/nav_graph.xml
index 71c194a..42369a0 100644
--- a/feature/src/main/res/navigation/nav_graph.xml
+++ b/feature/src/main/res/navigation/nav_graph.xml
@@ -15,7 +15,9 @@
app:destination="@id/fragment_home_detail" />
+ app:destination="@id/fragment_my_page"
+ app:popUpTo="@id/fragment_home"
+ app:popUpToInclusive="true" />
+ tools:layout="@layout/fragment_my_page">
+
+
+
+
+