diff --git a/app/src/main/java/kr/co/vividnext/sodalive/v2/main/MainV2Activity.kt b/app/src/main/java/kr/co/vividnext/sodalive/v2/main/MainV2Activity.kt index 06f7b569..19c2f4b0 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/v2/main/MainV2Activity.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/v2/main/MainV2Activity.kt @@ -147,12 +147,12 @@ class MainV2Activity : BaseActivity(ActivityMainV2Binding setupBottomNavigation() if (intent.hasExtra(EXTRA_CHAT_FILTER)) { - viewModel.clickTab(MainV2Tab.CHAT) + selectChatTabWithLoginGuard() } } fun showLoginActivity() { - if (SharedPreferenceManager.token.isBlank()) { + if (!isLoggedIn()) { val extras = intent.extras startActivity( Intent(applicationContext, LoginActivity::class.java).apply { @@ -165,7 +165,7 @@ class MainV2Activity : BaseActivity(ActivityMainV2Binding } fun openChatTab() { - viewModel.clickTab(MainV2Tab.CHAT) + selectChatTabWithLoginGuard() } private fun consumeInitialChatFilter(): ChatRoomFilter? { @@ -182,18 +182,27 @@ class MainV2Activity : BaseActivity(ActivityMainV2Binding return } - viewModel.clickTab(MainV2Tab.CHAT) + selectChatTabWithLoginGuard() } private fun setupBottomNavigation() { binding.bottomNavigation.setOnItemSelectedListener { item -> when (item.itemId) { - R.id.menu_main_v2_home -> viewModel.clickTab(MainV2Tab.HOME) - R.id.menu_main_v2_content -> viewModel.clickTab(MainV2Tab.CONTENT) - R.id.menu_main_v2_chat -> viewModel.clickTab(MainV2Tab.CHAT) - R.id.menu_main_v2_my -> viewModel.clickTab(MainV2Tab.MY) + R.id.menu_main_v2_home -> { + viewModel.clickTab(MainV2Tab.HOME) + 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 } - true } binding.bottomNavigation.apply { @@ -247,6 +256,16 @@ class MainV2Activity : BaseActivity(ActivityMainV2Binding fragmentTransaction.commitNow() } + private fun selectChatTabWithLoginGuard(): Boolean { + if (!isLoggedIn()) { + showLoginActivity() + return false + } + + viewModel.clickTab(MainV2Tab.CHAT) + return true + } + private fun observePlayerState() { playerStateJob = lifecycleScope.launch { repeatOnLifecycle(Lifecycle.State.STARTED) { diff --git a/app/src/test/java/kr/co/vividnext/sodalive/v2/main/MainV2ActivitySourceTest.kt b/app/src/test/java/kr/co/vividnext/sodalive/v2/main/MainV2ActivitySourceTest.kt index 2479e118..df69560f 100644 --- a/app/src/test/java/kr/co/vividnext/sodalive/v2/main/MainV2ActivitySourceTest.kt +++ b/app/src/test/java/kr/co/vividnext/sodalive/v2/main/MainV2ActivitySourceTest.kt @@ -46,6 +46,48 @@ class MainV2ActivitySourceTest { 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 { val candidates = listOf(File(relativePath), File("../$relativePath")) return candidates.firstOrNull { it.exists() }