fix(main): 대화 탭 로그인 가드를 적용한다

This commit is contained in:
2026-06-27 04:47:57 +09:00
parent 0679dc7deb
commit 0454980fae
2 changed files with 70 additions and 9 deletions

View File

@@ -147,12 +147,12 @@ class MainV2Activity : BaseActivity<ActivityMainV2Binding>(ActivityMainV2Binding
setupBottomNavigation() setupBottomNavigation()
if (intent.hasExtra(EXTRA_CHAT_FILTER)) { if (intent.hasExtra(EXTRA_CHAT_FILTER)) {
viewModel.clickTab(MainV2Tab.CHAT) selectChatTabWithLoginGuard()
} }
} }
fun showLoginActivity() { fun showLoginActivity() {
if (SharedPreferenceManager.token.isBlank()) { if (!isLoggedIn()) {
val extras = intent.extras val extras = intent.extras
startActivity( startActivity(
Intent(applicationContext, LoginActivity::class.java).apply { Intent(applicationContext, LoginActivity::class.java).apply {
@@ -165,7 +165,7 @@ class MainV2Activity : BaseActivity<ActivityMainV2Binding>(ActivityMainV2Binding
} }
fun openChatTab() { fun openChatTab() {
viewModel.clickTab(MainV2Tab.CHAT) selectChatTabWithLoginGuard()
} }
private fun consumeInitialChatFilter(): ChatRoomFilter? { private fun consumeInitialChatFilter(): ChatRoomFilter? {
@@ -182,19 +182,28 @@ class MainV2Activity : BaseActivity<ActivityMainV2Binding>(ActivityMainV2Binding
return return
} }
viewModel.clickTab(MainV2Tab.CHAT) selectChatTabWithLoginGuard()
} }
private fun setupBottomNavigation() { private fun setupBottomNavigation() {
binding.bottomNavigation.setOnItemSelectedListener { item -> binding.bottomNavigation.setOnItemSelectedListener { item ->
when (item.itemId) { when (item.itemId) {
R.id.menu_main_v2_home -> viewModel.clickTab(MainV2Tab.HOME) R.id.menu_main_v2_home -> {
R.id.menu_main_v2_content -> viewModel.clickTab(MainV2Tab.CONTENT) viewModel.clickTab(MainV2Tab.HOME)
R.id.menu_main_v2_chat -> viewModel.clickTab(MainV2Tab.CHAT)
R.id.menu_main_v2_my -> viewModel.clickTab(MainV2Tab.MY)
}
true true
} }
R.id.menu_main_v2_content -> {
viewModel.clickTab(MainV2Tab.CONTENT)
true
}
R.id.menu_main_v2_chat -> selectChatTabWithLoginGuard()
R.id.menu_main_v2_my -> {
viewModel.clickTab(MainV2Tab.MY)
true
}
else -> false
}
}
binding.bottomNavigation.apply { binding.bottomNavigation.apply {
itemIconTintList = null itemIconTintList = null
@@ -247,6 +256,16 @@ class MainV2Activity : BaseActivity<ActivityMainV2Binding>(ActivityMainV2Binding
fragmentTransaction.commitNow() fragmentTransaction.commitNow()
} }
private fun selectChatTabWithLoginGuard(): Boolean {
if (!isLoggedIn()) {
showLoginActivity()
return false
}
viewModel.clickTab(MainV2Tab.CHAT)
return true
}
private fun observePlayerState() { private fun observePlayerState() {
playerStateJob = lifecycleScope.launch { playerStateJob = lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) { repeatOnLifecycle(Lifecycle.State.STARTED) {

View File

@@ -46,6 +46,48 @@ class MainV2ActivitySourceTest {
assertTrue(dmRouteIndex < firstFallbackIndex) assertTrue(dmRouteIndex < firstFallbackIndex)
} }
@Test
fun `MainV2Activity 대화 탭 이동은 로그인 가드를 통과한 뒤 탭을 전환한다`() {
val source = projectFile("app/src/main/java/kr/co/vividnext/sodalive/v2/main/MainV2Activity.kt").readText()
assertTrue(source.contains("private fun selectChatTabWithLoginGuard(): Boolean"))
val guardSource = source.substringFrom("private fun selectChatTabWithLoginGuard(): Boolean")
assertBefore(guardSource, "if (!isLoggedIn())", "viewModel.clickTab(MainV2Tab.CHAT)")
assertBefore(guardSource, "showLoginActivity()", "return false")
assertTrue(guardSource.contains("return true"))
val setupViewSource = source.substringFrom("override fun setupView()")
assertTrue(setupViewSource.contains("selectChatTabWithLoginGuard()"))
assertFalse(setupViewSource.contains("viewModel.clickTab(MainV2Tab.CHAT)"))
val openChatTabSource = source.substringFrom("fun openChatTab()")
assertTrue(openChatTabSource.contains("selectChatTabWithLoginGuard()"))
assertFalse(openChatTabSource.contains("viewModel.clickTab(MainV2Tab.CHAT)"))
val openChatFilterSource = source.substringFrom("private fun openChatWithInitialFilter()")
assertTrue(openChatFilterSource.contains("selectChatTabWithLoginGuard()"))
assertFalse(openChatFilterSource.contains("viewModel.clickTab(MainV2Tab.CHAT)"))
val navigationSource = source.substringFrom("private fun setupBottomNavigation()")
assertTrue(navigationSource.contains("R.id.menu_main_v2_chat -> selectChatTabWithLoginGuard()"))
}
private fun assertBefore(source: String, expectedBefore: String, expectedAfter: String) {
val beforeIndex = source.indexOf(expectedBefore)
val afterIndex = source.indexOf(expectedAfter, beforeIndex)
assertTrue("Missing source: $expectedBefore", beforeIndex >= 0)
assertTrue("Missing source after $expectedBefore: $expectedAfter", afterIndex > beforeIndex)
}
private fun String.substringFrom(marker: String): String {
val startIndex = indexOf(marker)
assertTrue("Missing function: $marker", startIndex >= 0)
val nextFunctionIndex = indexOf("\n private fun ", startIndex + marker.length).takeIf { it >= 0 } ?: length
return substring(startIndex, nextFunctionIndex)
}
private fun projectFile(relativePath: String): File { private fun projectFile(relativePath: String): File {
val candidates = listOf(File(relativePath), File("../$relativePath")) val candidates = listOf(File(relativePath), File("../$relativePath"))
return candidates.firstOrNull { it.exists() } return candidates.firstOrNull { it.exists() }