refactor(home): 홈 접근 가드를 공통화한다

This commit is contained in:
2026-07-14 20:44:42 +09:00
parent d5d3444c3a
commit 7e12aa8720
3 changed files with 34 additions and 33 deletions

View File

@@ -7,7 +7,6 @@ import androidx.recyclerview.widget.LinearLayoutManager
import kr.co.vividnext.sodalive.R import kr.co.vividnext.sodalive.R
import kr.co.vividnext.sodalive.base.BaseFragment import kr.co.vividnext.sodalive.base.BaseFragment
import kr.co.vividnext.sodalive.common.LoadingDialog import kr.co.vividnext.sodalive.common.LoadingDialog
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
import kr.co.vividnext.sodalive.common.ToastMessage import kr.co.vividnext.sodalive.common.ToastMessage
import kr.co.vividnext.sodalive.common.formatUtcRelativeTimeText import kr.co.vividnext.sodalive.common.formatUtcRelativeTimeText
import kr.co.vividnext.sodalive.databinding.FragmentV2MainHomeBinding import kr.co.vividnext.sodalive.databinding.FragmentV2MainHomeBinding
@@ -25,7 +24,8 @@ import kr.co.vividnext.sodalive.v2.live.onair.HomeOnAirLiveActivity
import kr.co.vividnext.sodalive.v2.main.chat.dm.DmChatRoomActivity import kr.co.vividnext.sodalive.v2.main.chat.dm.DmChatRoomActivity
import kr.co.vividnext.sodalive.v2.main.chat.model.ChatRoomListUiItem import kr.co.vividnext.sodalive.v2.main.chat.model.ChatRoomListUiItem
import kr.co.vividnext.sodalive.v2.main.chat.model.ChatRoomType import kr.co.vividnext.sodalive.v2.main.chat.model.ChatRoomType
import kr.co.vividnext.sodalive.v2.main.ensureMainV2NavigationAllowed import kr.co.vividnext.sodalive.v2.access.AccessRequirement
import kr.co.vividnext.sodalive.v2.access.ensureV2Access
import kr.co.vividnext.sodalive.v2.main.home.model.HomeFollowingChatSection import kr.co.vividnext.sodalive.v2.main.home.model.HomeFollowingChatSection
import kr.co.vividnext.sodalive.v2.main.home.model.HomeFollowingCreatorSection import kr.co.vividnext.sodalive.v2.main.home.model.HomeFollowingCreatorSection
import kr.co.vividnext.sodalive.v2.main.home.model.HomeFollowingLiveSection import kr.co.vividnext.sodalive.v2.main.home.model.HomeFollowingLiveSection
@@ -166,7 +166,7 @@ class HomeMainFragment : BaseFragment<FragmentV2MainHomeBinding>(
} }
private fun openWithLoginGuard(activityClass: Class<*>) { private fun openWithLoginGuard(activityClass: Class<*>) {
ensureMainV2NavigationAllowed { ensureV2Access(AccessRequirement.Login) {
startActivity(Intent(requireContext(), activityClass)) startActivity(Intent(requireContext(), activityClass))
} }
} }
@@ -270,13 +270,14 @@ class HomeMainFragment : BaseFragment<FragmentV2MainHomeBinding>(
} }
private fun openFollowingTab() { private fun openFollowingTab() {
if (SharedPreferenceManager.token.isBlank()) { val allowed = ensureV2Access(AccessRequirement.Login)
if (!allowed) {
binding.textTabBarHome.root.selectTab(currentHomeTabIndex) binding.textTabBarHome.root.selectTab(currentHomeTabIndex)
return
} }
ensureMainV2NavigationAllowed {
showHomeTab(HOME_TAB_FOLLOWING) showHomeTab(HOME_TAB_FOLLOWING)
} }
}
private fun showHomeTab(index: Int) { private fun showHomeTab(index: Int) {
currentHomeTabIndex = index currentHomeTabIndex = index
@@ -532,10 +533,10 @@ class HomeMainFragment : BaseFragment<FragmentV2MainHomeBinding>(
} }
private fun onLiveClick(item: HomeRecommendationLiveUiModel) { private fun onLiveClick(item: HomeRecommendationLiveUiModel) {
ensureMainV2NavigationAllowed { ensureV2Access(AccessRequirement.Login) {
liveViewModel.getRoomDetail(item.roomId) { roomDetail -> liveViewModel.getRoomDetail(item.roomId) { roomDetail ->
if (!isAdded || view == null) return@getRoomDetail if (!isAdded || view == null) return@getRoomDetail
ensureMainV2NavigationAllowed(requiresAdultContentAccess = roomDetail.isAdult) { ensureV2Access(AccessRequirement.forAdultContent(roomDetail.isAdult)) {
liveCoordinator.enterLiveRoom(item.roomId, roomDetail) liveCoordinator.enterLiveRoom(item.roomId, roomDetail)
} }
} }
@@ -543,7 +544,7 @@ class HomeMainFragment : BaseFragment<FragmentV2MainHomeBinding>(
} }
private fun openHomeOnAirLive() { private fun openHomeOnAirLive() {
ensureMainV2NavigationAllowed { ensureV2Access(AccessRequirement.Login) {
startActivity(HomeOnAirLiveActivity.newIntent(requireContext())) startActivity(HomeOnAirLiveActivity.newIntent(requireContext()))
} }
} }
@@ -558,19 +559,19 @@ class HomeMainFragment : BaseFragment<FragmentV2MainHomeBinding>(
val community = item as? HomeFollowingNewsUiItem.Community ?: return val community = item as? HomeFollowingNewsUiItem.Community ?: return
val postId = community.postId val postId = community.postId
if (postId <= 0L) return if (postId <= 0L) return
ensureMainV2NavigationAllowed { ensureV2Access(AccessRequirement.Login) {
startActivity(CreatorChannelCommunityDetailActivity.newIntent(requireContext(), postId)) startActivity(CreatorChannelCommunityDetailActivity.newIntent(requireContext(), postId))
} }
} }
private fun openFollowingCreatorAll() { private fun openFollowingCreatorAll() {
ensureMainV2NavigationAllowed { ensureV2Access(AccessRequirement.Login) {
startActivity(Intent(requireContext(), FollowingCreatorActivity::class.java)) startActivity(Intent(requireContext(), FollowingCreatorActivity::class.java))
} }
} }
private fun openFollowingChat(item: ChatRoomListUiItem) { private fun openFollowingChat(item: ChatRoomListUiItem) {
ensureMainV2NavigationAllowed { ensureV2Access(AccessRequirement.Login) {
when (item.chatType) { when (item.chatType) {
ChatRoomType.AI -> startActivity(ChatRoomActivity.newIntent(requireContext(), item.roomId)) ChatRoomType.AI -> startActivity(ChatRoomActivity.newIntent(requireContext(), item.roomId))
ChatRoomType.DM -> startActivity(DmChatRoomActivity.newIntentByRoomId(requireContext(), item.roomId)) ChatRoomType.DM -> startActivity(DmChatRoomActivity.newIntentByRoomId(requireContext(), item.roomId))
@@ -580,21 +581,21 @@ class HomeMainFragment : BaseFragment<FragmentV2MainHomeBinding>(
private fun onBannerClick(item: HomeRecommendationBannerUiModel) { private fun onBannerClick(item: HomeRecommendationBannerUiModel) {
val route = item.toHomeRecommendationBannerRoute() ?: return val route = item.toHomeRecommendationBannerRoute() ?: return
ensureMainV2NavigationAllowed { ensureV2Access(AccessRequirement.Login) {
startActivity(route.toHomeRecommendationBannerIntent(requireContext())) startActivity(route.toHomeRecommendationBannerIntent(requireContext()))
} }
} }
private fun onRecentActivityClick(item: HomeRecommendationRecentlyActiveCreatorUiModel) { private fun onRecentActivityClick(item: HomeRecommendationRecentlyActiveCreatorUiModel) {
val route = item.toHomeRecommendationRecentlyActiveCreatorRoute() ?: return val route = item.toHomeRecommendationRecentlyActiveCreatorRoute() ?: return
ensureMainV2NavigationAllowed { ensureV2Access(AccessRequirement.Login) {
startActivity(route.toHomeRecommendationRecentlyActiveCreatorIntent(requireContext())) startActivity(route.toHomeRecommendationRecentlyActiveCreatorIntent(requireContext()))
} }
} }
private fun onAiCharacterClick(item: HomeRecommendationAiCharacterUiModel) { private fun onAiCharacterClick(item: HomeRecommendationAiCharacterUiModel) {
val route = item.toHomeRecommendationAiCharacterRoute() ?: return val route = item.toHomeRecommendationAiCharacterRoute() ?: return
ensureMainV2NavigationAllowed { ensureV2Access(AccessRequirement.Login) {
startActivity(route.toHomeRecommendationAiCharacterIntent(requireContext())) startActivity(route.toHomeRecommendationAiCharacterIntent(requireContext()))
} }
} }
@@ -605,7 +606,7 @@ class HomeMainFragment : BaseFragment<FragmentV2MainHomeBinding>(
} }
private fun openCreatorProfile(creatorId: Long) { private fun openCreatorProfile(creatorId: Long) {
ensureMainV2NavigationAllowed { ensureV2Access(AccessRequirement.Login) {
startActivity( startActivity(
CreatorChannelActivity.newIntent(requireContext(), creatorId) CreatorChannelActivity.newIntent(requireContext(), creatorId)
) )
@@ -614,7 +615,7 @@ class HomeMainFragment : BaseFragment<FragmentV2MainHomeBinding>(
private fun openPopularCommunityPost(item: FeedItem.Community) { private fun openPopularCommunityPost(item: FeedItem.Community) {
val postId = item.postId.toLongOrNull() ?: return val postId = item.postId.toLongOrNull() ?: return
ensureMainV2NavigationAllowed { ensureV2Access(AccessRequirement.Login) {
startActivity(CreatorChannelCommunityDetailActivity.newIntent(requireContext(), postId)) startActivity(CreatorChannelCommunityDetailActivity.newIntent(requireContext(), postId))
} }
} }

View File

@@ -13,7 +13,7 @@ class HomeMainFragmentLoginGuardSourceTest {
"app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainFragment.kt" "app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainFragment.kt"
).readText() ).readText()
assertTrue(source.contains("import kr.co.vividnext.sodalive.v2.main.ensureMainV2NavigationAllowed")) assertTrue(source.contains("import kr.co.vividnext.sodalive.v2.access.ensureV2Access"))
assertGuardedStartActivity(source, "private fun openHomeOnAirLive()") assertGuardedStartActivity(source, "private fun openHomeOnAirLive()")
assertGuardedStartActivity(source, "private fun openFollowingChat(item: ChatRoomListUiItem)") assertGuardedStartActivity(source, "private fun openFollowingChat(item: ChatRoomListUiItem)")
assertGuardedStartActivity(source, "private fun onBannerClick(item: HomeRecommendationBannerUiModel)") assertGuardedStartActivity(source, "private fun onBannerClick(item: HomeRecommendationBannerUiModel)")
@@ -65,12 +65,12 @@ class HomeMainFragmentLoginGuardSourceTest {
assertBefore( assertBefore(
clickSource, clickSource,
"val community = item as? HomeFollowingNewsUiItem.Community ?: return", "val community = item as? HomeFollowingNewsUiItem.Community ?: return",
"ensureMainV2NavigationAllowed" "ensureV2Access"
) )
assertBefore( assertBefore(
clickSource, clickSource,
"if (postId <= 0L) return", "if (postId <= 0L) return",
"ensureMainV2NavigationAllowed" "ensureV2Access"
) )
assertTrue(clickSource.contains("CreatorChannelCommunityDetailActivity.newIntent(requireContext(), postId)")) assertTrue(clickSource.contains("CreatorChannelCommunityDetailActivity.newIntent(requireContext(), postId)"))
assertFalse(clickSource.contains("CreatorCommunityAllActivity")) assertFalse(clickSource.contains("CreatorCommunityAllActivity"))
@@ -98,15 +98,15 @@ class HomeMainFragmentLoginGuardSourceTest {
"app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainFragment.kt" "app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainFragment.kt"
).readText() ).readText()
assertTrue(source.contains("import kr.co.vividnext.sodalive.common.SharedPreferenceManager")) assertTrue(source.contains("import kr.co.vividnext.sodalive.v2.access.AccessRequirement"))
assertTrue(source.contains("private var currentHomeTabIndex = HOME_TAB_RECOMMENDATION")) assertTrue(source.contains("private var currentHomeTabIndex = HOME_TAB_RECOMMENDATION"))
val followingTabSource = source.substringFrom("private fun openFollowingTab()") val followingTabSource = source.substringFrom("private fun openFollowingTab()")
assertTrue(followingTabSource.contains("if (SharedPreferenceManager.token.isBlank())")) assertTrue(followingTabSource.contains("val allowed = ensureV2Access(AccessRequirement.Login)"))
assertBefore( assertBefore(
followingTabSource, followingTabSource,
"binding.textTabBarHome.root.selectTab(currentHomeTabIndex)", "val allowed = ensureV2Access(AccessRequirement.Login)",
"ensureMainV2NavigationAllowed" "binding.textTabBarHome.root.selectTab(currentHomeTabIndex)"
) )
assertTrue(followingTabSource.contains("showHomeTab(HOME_TAB_FOLLOWING)")) assertTrue(followingTabSource.contains("showHomeTab(HOME_TAB_FOLLOWING)"))
@@ -121,21 +121,21 @@ class HomeMainFragmentLoginGuardSourceTest {
).readText() ).readText()
val clickSource = source.substringFrom("private fun onLiveClick(item: HomeRecommendationLiveUiModel)") val clickSource = source.substringFrom("private fun onLiveClick(item: HomeRecommendationLiveUiModel)")
assertTrue(clickSource.contains("ensureMainV2NavigationAllowed")) assertTrue(clickSource.contains("ensureV2Access"))
assertTrue(clickSource.contains("liveViewModel.getRoomDetail(item.roomId) { roomDetail ->")) assertTrue(clickSource.contains("liveViewModel.getRoomDetail(item.roomId) { roomDetail ->"))
assertBefore( assertBefore(
clickSource, clickSource,
"if (!isAdded || view == null) return@getRoomDetail", "if (!isAdded || view == null) return@getRoomDetail",
"requiresAdultContentAccess = roomDetail.isAdult" "AccessRequirement.forAdultContent(roomDetail.isAdult)"
) )
assertBefore( assertBefore(
clickSource, clickSource,
"liveViewModel.getRoomDetail(item.roomId) { roomDetail ->", "liveViewModel.getRoomDetail(item.roomId) { roomDetail ->",
"requiresAdultContentAccess = roomDetail.isAdult" "AccessRequirement.forAdultContent(roomDetail.isAdult)"
) )
assertBefore( assertBefore(
clickSource, clickSource,
"requiresAdultContentAccess = roomDetail.isAdult", "AccessRequirement.forAdultContent(roomDetail.isAdult)",
"liveCoordinator.enterLiveRoom(item.roomId, roomDetail)" "liveCoordinator.enterLiveRoom(item.roomId, roomDetail)"
) )
assertFalse(clickSource.contains("= Unit")) assertFalse(clickSource.contains("= Unit"))
@@ -189,14 +189,14 @@ class HomeMainFragmentLoginGuardSourceTest {
private fun assertGuardedStartActivity(source: String, functionSignature: String) { private fun assertGuardedStartActivity(source: String, functionSignature: String) {
val functionSource = source.substringFrom(functionSignature) val functionSource = source.substringFrom(functionSignature)
assertTrue( assertTrue(
"$functionSignature must call ensureMainV2NavigationAllowed before startActivity.", "$functionSignature must call ensureV2Access before startActivity.",
functionSource.indexOf("ensureMainV2NavigationAllowed") in 0 until functionSource.indexOf("startActivity") functionSource.indexOf("ensureV2Access") in 0 until functionSource.indexOf("startActivity")
) )
} }
private fun assertBeforeGuard(source: String, expectedReturn: String) { private fun assertBeforeGuard(source: String, expectedReturn: String) {
val returnIndex = source.indexOf(expectedReturn) val returnIndex = source.indexOf(expectedReturn)
val guardIndex = source.indexOf("ensureMainV2NavigationAllowed", returnIndex) val guardIndex = source.indexOf("ensureV2Access", returnIndex)
assertTrue("Missing source: $expectedReturn", returnIndex >= 0) assertTrue("Missing source: $expectedReturn", returnIndex >= 0)
assertTrue("$expectedReturn must stay before guard.", guardIndex > returnIndex) assertTrue("$expectedReturn must stay before guard.", guardIndex > returnIndex)

View File

@@ -15,7 +15,7 @@ class HomeMainTitleBarActionSourceTest {
assertTrue(source.contains("viewHomeTitleBar.ivTitleBarCash.setOnClickListener")) assertTrue(source.contains("viewHomeTitleBar.ivTitleBarCash.setOnClickListener"))
assertTrue(source.contains("viewHomeTitleBar.ivTitleBarSearch.setOnClickListener")) assertTrue(source.contains("viewHomeTitleBar.ivTitleBarSearch.setOnClickListener"))
assertTrue(source.contains("viewHomeTitleBar.ivTitleBarBell.setOnClickListener")) assertTrue(source.contains("viewHomeTitleBar.ivTitleBarBell.setOnClickListener"))
assertTrue(source.contains("ensureMainV2NavigationAllowed")) assertTrue(source.contains("ensureV2Access"))
assertTrue(source.contains("CanChargeActivity::class.java")) assertTrue(source.contains("CanChargeActivity::class.java"))
assertTrue(source.contains("SearchActivity::class.java")) assertTrue(source.contains("SearchActivity::class.java"))
assertTrue(source.contains("PushNotificationListActivity::class.java")) assertTrue(source.contains("PushNotificationListActivity::class.java"))