feat(creator-channel): 홈 섹션 이동을 연결한다
This commit is contained in:
@@ -546,6 +546,11 @@ class CreatorChannelActivity :
|
||||
updateViewPagerHeight()
|
||||
}
|
||||
|
||||
override fun onCreatorChannelHomeTabRequested(tab: CreatorChannelTab) {
|
||||
selectCreatorChannelTab(tab)
|
||||
scrollCreatorChannelToTop()
|
||||
}
|
||||
|
||||
override fun onCreatorChannelLiveContentChanged() {
|
||||
updateCreatorChannelTabViewportHeight()
|
||||
updateViewPagerHeight {
|
||||
@@ -1184,6 +1189,14 @@ class CreatorChannelActivity :
|
||||
)
|
||||
}
|
||||
|
||||
private fun selectCreatorChannelTab(tab: CreatorChannelTab) {
|
||||
binding.viewPager.currentItem = tab.ordinal
|
||||
}
|
||||
|
||||
private fun scrollCreatorChannelToTop() {
|
||||
binding.nestedScrollView.scrollTo(0, 0)
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
binding.btnCreatorChannelOwnerCta.isEnabled = true
|
||||
|
||||
@@ -12,6 +12,7 @@ import kr.co.vividnext.sodalive.v2.creator.channel.data.CreatorChannelScheduleRe
|
||||
import kr.co.vividnext.sodalive.v2.creator.channel.data.CreatorChannelSeriesResponse
|
||||
import kr.co.vividnext.sodalive.v2.creator.channel.model.CreatorChannelHeaderUiModel
|
||||
import kr.co.vividnext.sodalive.v2.creator.channel.model.CreatorChannelHomeUiState
|
||||
import kr.co.vividnext.sodalive.v2.creator.channel.model.CreatorChannelTab
|
||||
import kr.co.vividnext.sodalive.v2.creator.channel.ui.CreatorChannelHomeSectionAdapter
|
||||
import org.koin.androidx.viewmodel.ext.android.viewModel
|
||||
|
||||
@@ -25,7 +26,9 @@ class CreatorChannelHomeFragment : BaseFragment<FragmentCreatorChannelHomeBindin
|
||||
onScheduleClick = ::onScheduleClicked,
|
||||
onAudioContentClick = ::onAudioContentClicked,
|
||||
onSeriesClick = ::onSeriesClicked,
|
||||
onDonationClick = ::onDonationClicked
|
||||
onDonationClick = ::onDonationClicked,
|
||||
onSectionChevronClick = ::onSectionChevronClicked,
|
||||
onCommunityClick = ::onCommunityClicked
|
||||
)
|
||||
private val creatorId: Long by lazy { arguments?.getLong(ARG_CREATOR_ID) ?: 0L }
|
||||
private val host: Host
|
||||
@@ -123,6 +126,14 @@ class CreatorChannelHomeFragment : BaseFragment<FragmentCreatorChannelHomeBindin
|
||||
host.onCreatorChannelDonationClicked()
|
||||
}
|
||||
|
||||
private fun onSectionChevronClicked(tab: CreatorChannelTab) {
|
||||
host.onCreatorChannelHomeTabRequested(tab)
|
||||
}
|
||||
|
||||
private fun onCommunityClicked(postId: Long) {
|
||||
host.onCreatorChannelCommunityPostClicked(postId)
|
||||
}
|
||||
|
||||
private fun onCurrentLiveClicked(live: CreatorChannelLiveResponse) {
|
||||
host.onCreatorChannelCurrentLiveClicked(live)
|
||||
}
|
||||
@@ -137,6 +148,8 @@ class CreatorChannelHomeFragment : BaseFragment<FragmentCreatorChannelHomeBindin
|
||||
fun onCreatorChannelHomeActionDelegateReady(delegate: HomeActionDelegate?)
|
||||
fun onCreatorChannelHomeContentChanged()
|
||||
fun onCreatorChannelDonationClicked()
|
||||
fun onCreatorChannelHomeTabRequested(tab: CreatorChannelTab)
|
||||
fun onCreatorChannelCommunityPostClicked(postId: Long)
|
||||
fun onCreatorChannelCurrentLiveClicked(live: CreatorChannelLiveResponse)
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ import kr.co.vividnext.sodalive.v2.creator.channel.data.CreatorChannelLiveRespon
|
||||
import kr.co.vividnext.sodalive.v2.creator.channel.data.CreatorChannelScheduleResponse
|
||||
import kr.co.vividnext.sodalive.v2.creator.channel.data.CreatorChannelSeriesResponse
|
||||
import kr.co.vividnext.sodalive.v2.creator.channel.model.CreatorChannelHomeSection
|
||||
import kr.co.vividnext.sodalive.v2.creator.channel.model.CreatorChannelTab
|
||||
import kr.co.vividnext.sodalive.v2.widget.feed.FeedCommunityView
|
||||
import kr.co.vividnext.sodalive.v2.widget.feed.FeedItem
|
||||
import kr.co.vividnext.sodalive.v2.widget.feed.FeedSize
|
||||
@@ -39,7 +40,9 @@ class CreatorChannelHomeSectionAdapter(
|
||||
private val onScheduleClick: (CreatorChannelScheduleResponse) -> Unit = {},
|
||||
private val onAudioContentClick: (CreatorChannelAudioContentResponse) -> Unit = {},
|
||||
private val onSeriesClick: (CreatorChannelSeriesResponse) -> Unit = {},
|
||||
private val onDonationClick: () -> Unit = {}
|
||||
private val onDonationClick: () -> Unit = {},
|
||||
private val onSectionChevronClick: (CreatorChannelTab) -> Unit = {},
|
||||
private val onCommunityClick: (Long) -> Unit = {}
|
||||
) : RecyclerView.Adapter<CreatorChannelHomeSectionAdapter.SectionViewHolder>() {
|
||||
|
||||
private var items: List<CreatorChannelHomeSection> = emptyList()
|
||||
@@ -53,7 +56,16 @@ class CreatorChannelHomeSectionAdapter(
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SectionViewHolder {
|
||||
val view = LayoutInflater.from(parent.context).inflate(viewType, parent, false)
|
||||
return SectionViewHolder(view, onLiveClick, onScheduleClick, onAudioContentClick, onSeriesClick, onDonationClick)
|
||||
return SectionViewHolder(
|
||||
view,
|
||||
onLiveClick,
|
||||
onScheduleClick,
|
||||
onAudioContentClick,
|
||||
onSeriesClick,
|
||||
onDonationClick,
|
||||
onSectionChevronClick,
|
||||
onCommunityClick
|
||||
)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: SectionViewHolder, position: Int) {
|
||||
@@ -68,9 +80,12 @@ class CreatorChannelHomeSectionAdapter(
|
||||
private val onScheduleClick: (CreatorChannelScheduleResponse) -> Unit,
|
||||
private val onAudioContentClick: (CreatorChannelAudioContentResponse) -> Unit,
|
||||
private val onSeriesClick: (CreatorChannelSeriesResponse) -> Unit,
|
||||
private val onDonationClick: () -> Unit
|
||||
private val onDonationClick: () -> Unit,
|
||||
private val onSectionChevronClick: (CreatorChannelTab) -> Unit,
|
||||
private val onCommunityClick: (Long) -> Unit
|
||||
) : RecyclerView.ViewHolder(view) {
|
||||
private val title: TextView? = view.findViewById(R.id.tv_section_title)
|
||||
private val sectionTitleChevron: ImageView? = view.findViewById(R.id.iv_section_title_chevron)
|
||||
private val currentLiveTitle: TextView? = view.findViewById(R.id.tv_current_live_title)
|
||||
private val currentLiveStartTime: TextView? = view.findViewById(R.id.tv_current_live_start_time)
|
||||
private val currentLivePrice: TextView? = view.findViewById(R.id.tv_current_live_price)
|
||||
@@ -93,6 +108,7 @@ class CreatorChannelHomeSectionAdapter(
|
||||
private val audioContentsRecyclerView: RecyclerView? = view.findViewById(R.id.rv_audio_contents)
|
||||
private val seriesItems: LinearLayout? = view.findViewById(R.id.ll_series_items)
|
||||
private val communityItems: LinearLayout? = view.findViewById(R.id.ll_community_items)
|
||||
private val communityMoreButton: View? = view.findViewById(R.id.layout_community_more_button)
|
||||
private val fanTalkCard: View? = view.findViewById(R.id.layout_fantalk_card)
|
||||
private val fanTalkTotalRow: View? = view.findViewById(R.id.layout_fantalk_total_row)
|
||||
private val fanTalkLatestRow: View? = view.findViewById(R.id.layout_fantalk_latest_row)
|
||||
@@ -120,6 +136,11 @@ class CreatorChannelHomeSectionAdapter(
|
||||
fun bind(item: CreatorChannelHomeSection) {
|
||||
itemView.setOnClickListener(null)
|
||||
title?.setText(item.titleResId)
|
||||
sectionTitleChevron?.isVisible = item.chevronTab != null
|
||||
sectionTitleChevron?.setOnClickListener {
|
||||
item.chevronTab?.let(onSectionChevronClick)
|
||||
}
|
||||
communityMoreButton?.setOnClickListener(null)
|
||||
donationItems?.removeAllViews()
|
||||
noticeItems?.removeAllViews()
|
||||
scheduleTimeline?.removeAllViews()
|
||||
@@ -351,6 +372,7 @@ class CreatorChannelHomeSectionAdapter(
|
||||
}
|
||||
|
||||
private fun bindCommunities(item: CreatorChannelHomeSection.Communities) {
|
||||
communityMoreButton?.setOnClickListener { onSectionChevronClick(CreatorChannelTab.Community) }
|
||||
val visibleCommunities = item.communities.take(MAX_COMMUNITY_ITEM_COUNT)
|
||||
visibleCommunities.forEachIndexed { index, community ->
|
||||
val communityWidthDp = calculateCreatorChannelCommunityCardWidthDp(
|
||||
@@ -377,6 +399,7 @@ class CreatorChannelHomeSectionAdapter(
|
||||
).apply {
|
||||
bottomMargin = if (index == visibleCommunities.lastIndex) 0 else 8.dp()
|
||||
}
|
||||
row.setOnClickListener { onCommunityClick(community.postId) }
|
||||
communityItems?.addView(row)
|
||||
}
|
||||
}
|
||||
@@ -590,6 +613,15 @@ class CreatorChannelHomeSectionAdapter(
|
||||
is CreatorChannelHomeSection.Sns -> R.string.creator_channel_section_sns
|
||||
}
|
||||
|
||||
val CreatorChannelHomeSection.chevronTab: CreatorChannelTab?
|
||||
get() = when (this) {
|
||||
is CreatorChannelHomeSection.Donations -> CreatorChannelTab.Donation
|
||||
is CreatorChannelHomeSection.AudioContents -> CreatorChannelTab.Audio
|
||||
is CreatorChannelHomeSection.Series -> CreatorChannelTab.Series
|
||||
is CreatorChannelHomeSection.FanTalk -> CreatorChannelTab.FanTalk
|
||||
else -> null
|
||||
}
|
||||
|
||||
private const val MAX_DONATION_ITEM_COUNT = 8
|
||||
private const val MAX_NOTICE_ITEM_COUNT = 3
|
||||
private const val MAX_SCHEDULE_ITEM_COUNT = 3
|
||||
|
||||
@@ -980,6 +980,68 @@ class CreatorChannelActivitySourceTest {
|
||||
assertTrue(activity.contains("dialog.show(screenWidth - 26.7f.dpToPx().toInt())"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `홈 섹션 chevron과 커뮤니티 전체보기는 대응 탭으로 이동한다`() {
|
||||
val adapter = projectFile(
|
||||
"app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/ui/CreatorChannelHomeSectionAdapter.kt"
|
||||
).readText()
|
||||
val fragment = projectFile(
|
||||
"app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelHomeFragment.kt"
|
||||
).readText()
|
||||
val activity = projectFile(
|
||||
"app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelActivity.kt"
|
||||
).readText()
|
||||
|
||||
assertTrue(adapter.contains("private val sectionTitleChevron: ImageView?"))
|
||||
assertTrue(adapter.contains("private val communityMoreButton: View?"))
|
||||
assertTrue(adapter.contains("sectionTitleChevron?.isVisible = item.chevronTab != null"))
|
||||
assertTrue(adapter.contains("sectionTitleChevron?.setOnClickListener"))
|
||||
assertTrue(adapter.contains("item.chevronTab?.let(onSectionChevronClick)"))
|
||||
assertTrue(
|
||||
adapter.contains(
|
||||
"communityMoreButton?.setOnClickListener { onSectionChevronClick(CreatorChannelTab.Community) }"
|
||||
)
|
||||
)
|
||||
assertTrue(adapter.contains("is CreatorChannelHomeSection.Donations -> CreatorChannelTab.Donation"))
|
||||
assertTrue(adapter.contains("is CreatorChannelHomeSection.AudioContents -> CreatorChannelTab.Audio"))
|
||||
assertTrue(adapter.contains("is CreatorChannelHomeSection.Series -> CreatorChannelTab.Series"))
|
||||
assertTrue(adapter.contains("is CreatorChannelHomeSection.FanTalk -> CreatorChannelTab.FanTalk"))
|
||||
assertTrue(fragment.contains("onSectionChevronClick = ::onSectionChevronClicked"))
|
||||
assertTrue(fragment.contains("host.onCreatorChannelHomeTabRequested(tab)"))
|
||||
assertTrue(activity.contains("override fun onCreatorChannelHomeTabRequested(tab: CreatorChannelTab)"))
|
||||
assertTrue(activity.contains("private fun selectCreatorChannelTab(tab: CreatorChannelTab)"))
|
||||
assertTrue(activity.contains("binding.viewPager.currentItem = tab.ordinal"))
|
||||
assertTrue(activity.contains("private fun scrollCreatorChannelToTop()"))
|
||||
assertTrue(activity.contains("binding.nestedScrollView.scrollTo(0, 0)"))
|
||||
assertTrue(
|
||||
activity.contains(
|
||||
"override fun onCreatorChannelHomeTabRequested(tab: CreatorChannelTab) {\n" +
|
||||
" selectCreatorChannelTab(tab)\n" +
|
||||
" scrollCreatorChannelToTop()"
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `홈 커뮤니티 아이템 클릭은 커뮤니티 상세 이동 host 계약을 사용한다`() {
|
||||
val adapter = projectFile(
|
||||
"app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/ui/CreatorChannelHomeSectionAdapter.kt"
|
||||
).readText()
|
||||
val fragment = projectFile(
|
||||
"app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelHomeFragment.kt"
|
||||
).readText()
|
||||
val activity = projectFile(
|
||||
"app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/CreatorChannelActivity.kt"
|
||||
).readText()
|
||||
|
||||
assertTrue(adapter.contains("private val onCommunityClick: (Long) -> Unit = {}"))
|
||||
assertTrue(adapter.contains("row.setOnClickListener { onCommunityClick(community.postId) }"))
|
||||
assertTrue(fragment.contains("onCommunityClick = ::onCommunityClicked"))
|
||||
assertTrue(fragment.contains("host.onCreatorChannelCommunityPostClicked(postId)"))
|
||||
assertTrue(activity.contains("override fun onCreatorChannelCommunityPostClicked(postId: Long)"))
|
||||
assertTrue(activity.contains("CreatorChannelCommunityDetailActivity.newIntent(this, postId)"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `후원 can 수량은 요청된 배경색 resource 경계로 매핑한다`() {
|
||||
assertEquals(R.color.gray_200, calculateCreatorChannelDonationHeaderColorRes(1))
|
||||
|
||||
Reference in New Issue
Block a user