From 658b4f0a9df7e0b44184a14c1ae76e7b0a1c4ea7 Mon Sep 17 00:00:00 2001 From: klaus Date: Tue, 30 Jun 2026 17:43:14 +0900 Subject: [PATCH] =?UTF-8?q?fix(home):=20=ED=8C=94=EB=A1=9C=EC=9E=89=20?= =?UTF-8?q?=ED=81=AC=EB=A6=AC=EC=97=90=EC=9D=B4=ED=84=B0=20=EC=A0=84?= =?UTF-8?q?=EC=B2=B4=20=EC=9D=B4=EB=8F=99=EC=9D=84=20=EC=97=B0=EA=B2=B0?= =?UTF-8?q?=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sodalive/v2/main/home/HomeMainFragment.kt | 12 +++++- .../home/ui/HomeFollowingCreatorAdapter.kt | 43 +++++++++++++++---- .../item_home_following_creator_all.xml | 28 ++++++++++++ .../home/HomeFollowingFragmentSourceTest.kt | 37 ++++++++++++++++ 4 files changed, 111 insertions(+), 9 deletions(-) create mode 100644 app/src/main/res/layout/item_home_following_creator_all.xml diff --git a/app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainFragment.kt b/app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainFragment.kt index cedb2daf..9edd61fb 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainFragment.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/HomeMainFragment.kt @@ -14,6 +14,7 @@ import kr.co.vividnext.sodalive.common.formatUtcRelativeTimeText import kr.co.vividnext.sodalive.databinding.FragmentV2MainHomeBinding import kr.co.vividnext.sodalive.databinding.ViewSectionTitleBinding import kr.co.vividnext.sodalive.explorer.profile.creator_community.all.CreatorCommunityAllActivity +import kr.co.vividnext.sodalive.following.FollowingCreatorActivity import kr.co.vividnext.sodalive.chat.talk.room.ChatRoomActivity import kr.co.vividnext.sodalive.home.pushnotification.PushNotificationListActivity import kr.co.vividnext.sodalive.mypage.can.charge.CanChargeActivity @@ -96,7 +97,10 @@ class HomeMainFragment : BaseFragment( ) private val popularCommunityAdapter = HomePopularCommunityAdapter { openPopularCommunityPost(it) } private val creatorRankingAdapter = CreatorRankingAdapter { openCreatorRankingProfile(it) } - private val followingCreatorAdapter = HomeFollowingCreatorAdapter { openCreatorProfile(it.creatorId) } + private val followingCreatorAdapter = HomeFollowingCreatorAdapter( + onClickItem = { openCreatorProfile(it.creatorId) }, + onClickAll = { openFollowingCreatorAll() } + ) private val followingLiveAdapter = HomeFollowingLiveAdapter { onFollowingLiveClick(it) } private val followingChatAdapter = HomeFollowingChatAdapter { openFollowingChat(it) } private val followingScheduleAdapter = HomeFollowingScheduleAdapter { onFollowingScheduleClick(it) } @@ -526,6 +530,12 @@ class HomeMainFragment : BaseFragment( private fun onFollowingNewsClick(item: HomeFollowingNewsUiItem) = Unit + private fun openFollowingCreatorAll() { + ensureMainV2NavigationAllowed { + startActivity(Intent(requireContext(), FollowingCreatorActivity::class.java)) + } + } + private fun openFollowingChat(item: ChatRoomListUiItem) { ensureMainV2NavigationAllowed { when (item.chatType) { diff --git a/app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/ui/HomeFollowingCreatorAdapter.kt b/app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/ui/HomeFollowingCreatorAdapter.kt index e5a8d18b..d472b65c 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/ui/HomeFollowingCreatorAdapter.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/ui/HomeFollowingCreatorAdapter.kt @@ -10,8 +10,9 @@ import kr.co.vividnext.sodalive.R import kr.co.vividnext.sodalive.v2.main.home.model.HomeFollowingCreatorUiItem class HomeFollowingCreatorAdapter( - private val onClickItem: (HomeFollowingCreatorUiItem) -> Unit = {} -) : RecyclerView.Adapter() { + private val onClickItem: (HomeFollowingCreatorUiItem) -> Unit = {}, + private val onClickAll: () -> Unit = {} +) : RecyclerView.Adapter() { private var items: List = emptyList() fun submitItems(items: List) { @@ -19,17 +20,29 @@ class HomeFollowingCreatorAdapter( notifyDataSetChanged() } - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CreatorViewHolder { - val view = LayoutInflater.from(parent.context).inflate(R.layout.item_home_following_creator, parent, false) + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { + val layoutResId = when (viewType) { + VIEW_TYPE_ALL -> R.layout.item_home_following_creator_all + else -> R.layout.item_home_following_creator + } + val view = LayoutInflater.from(parent.context).inflate(layoutResId, parent, false) view.layoutParams = recyclerItemLayoutParams(parent) - return CreatorViewHolder(view, onClickItem) + return when (viewType) { + VIEW_TYPE_ALL -> AllViewHolder(view, onClickAll) + else -> CreatorViewHolder(view, onClickItem) + } } - override fun onBindViewHolder(holder: CreatorViewHolder, position: Int) { - holder.bind(items[position]) + override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { + when (holder) { + is AllViewHolder -> holder.bind() + is CreatorViewHolder -> holder.bind(items[position]) + } } - override fun getItemCount(): Int = items.size + override fun getItemCount(): Int = items.size + if (items.isNotEmpty()) 1 else 0 + + override fun getItemViewType(position: Int): Int = if (position < items.size) VIEW_TYPE_CREATOR else VIEW_TYPE_ALL class CreatorViewHolder( itemView: View, @@ -44,4 +57,18 @@ class HomeFollowingCreatorAdapter( itemView.setOnClickListener { onClickItem(item) } } } + + class AllViewHolder( + itemView: View, + private val onClickAll: () -> Unit + ) : RecyclerView.ViewHolder(itemView) { + fun bind() { + itemView.setOnClickListener { onClickAll() } + } + } + + private companion object { + private const val VIEW_TYPE_CREATOR = 0 + private const val VIEW_TYPE_ALL = 1 + } } diff --git a/app/src/main/res/layout/item_home_following_creator_all.xml b/app/src/main/res/layout/item_home_following_creator_all.xml new file mode 100644 index 00000000..66c97b30 --- /dev/null +++ b/app/src/main/res/layout/item_home_following_creator_all.xml @@ -0,0 +1,28 @@ + + + + + + + diff --git a/app/src/test/java/kr/co/vividnext/sodalive/v2/main/home/HomeFollowingFragmentSourceTest.kt b/app/src/test/java/kr/co/vividnext/sodalive/v2/main/home/HomeFollowingFragmentSourceTest.kt index 5a50cd24..53736985 100644 --- a/app/src/test/java/kr/co/vividnext/sodalive/v2/main/home/HomeFollowingFragmentSourceTest.kt +++ b/app/src/test/java/kr/co/vividnext/sodalive/v2/main/home/HomeFollowingFragmentSourceTest.kt @@ -199,6 +199,38 @@ class HomeFollowingFragmentSourceTest { assertTrue(itemLayout.contains("@style/Typography.Body5")) } + @Test + fun `following creators list appends all button as last item`() { + val adapter = projectFile( + "app/src/main/java/kr/co/vividnext/sodalive/v2/main/home/ui/HomeFollowingCreatorAdapter.kt" + ).readText() + val fragment = homeMainFragmentSource() + val allLayoutFile = projectFileOrNull("app/src/main/res/layout/item_home_following_creator_all.xml") + + assertTrue(allLayoutFile != null) + val allLayout = allLayoutFile?.readText().orEmpty() + + assertTrue(adapter.contains("VIEW_TYPE_CREATOR")) + assertTrue(adapter.contains("VIEW_TYPE_ALL")) + assertTrue(adapter.contains("getItemViewType(position: Int)")) + assertTrue(adapter.contains("if (position < items.size) VIEW_TYPE_CREATOR else VIEW_TYPE_ALL")) + assertTrue(adapter.contains("override fun getItemCount(): Int = items.size + if (items.isNotEmpty()) 1 else 0")) + assertTrue(adapter.contains("R.layout.item_home_following_creator_all")) + assertTrue(adapter.contains("AllViewHolder")) + assertTrue(fragment.contains("import kr.co.vividnext.sodalive.following.FollowingCreatorActivity")) + assertTrue(fragment.contains("HomeFollowingCreatorAdapter(")) + assertTrue(fragment.contains("onClickAll = { openFollowingCreatorAll() }")) + assertTrue(fragment.contains("private fun openFollowingCreatorAll()")) + assertTrue(fragment.contains("startActivity(Intent(requireContext(), FollowingCreatorActivity::class.java))")) + assertTrue(allLayout.contains("android:layout_width=\"wrap_content\"")) + assertTrue(allLayout.contains("android:layout_height=\"wrap_content\"")) + assertTrue(allLayout.contains("android:layout_height=\"75dp\"")) + assertTrue(allLayout.contains("android:paddingHorizontal=\"16dp\"")) + assertTrue(allLayout.contains("android:textColor=\"@color/soda_400\"")) + assertTrue(allLayout.contains("android:visibility=\"invisible\"")) + assertTrue(allLayout.contains("@string/screen_home_theme_all")) + } + @Test fun `following recent chats section is horizontal box list`() { val layout = homeMainLayoutSource() @@ -246,4 +278,9 @@ class HomeFollowingFragmentSourceTest { val candidates = listOf(File(relativePath), File("../$relativePath")) return candidates.first { it.exists() }.canonicalFile } + + private fun projectFileOrNull(relativePath: String): File? { + val candidates = listOf(File(relativePath), File("../$relativePath")) + return candidates.firstOrNull { it.exists() }?.canonicalFile + } }