feat(home): 홈 추천 섹션 바인딩을 추가한다
This commit is contained in:
@@ -2,14 +2,54 @@ package kr.co.vividnext.sodalive.v2.main
|
|||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
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.databinding.FragmentV2MainHomeBinding
|
import kr.co.vividnext.sodalive.databinding.FragmentV2MainHomeBinding
|
||||||
import kr.co.vividnext.sodalive.databinding.ViewSectionTitleBinding
|
import kr.co.vividnext.sodalive.databinding.ViewSectionTitleBinding
|
||||||
|
import kr.co.vividnext.sodalive.v2.main.home.model.HomeRecommendationAiCharacterSection
|
||||||
|
import kr.co.vividnext.sodalive.v2.main.home.model.HomeRecommendationAiCharacterUiModel
|
||||||
|
import kr.co.vividnext.sodalive.v2.main.home.model.HomeRecommendationBannerSection
|
||||||
|
import kr.co.vividnext.sodalive.v2.main.home.model.HomeRecommendationBannerUiModel
|
||||||
|
import kr.co.vividnext.sodalive.v2.main.home.model.HomeRecommendationCheerCreatorSection
|
||||||
|
import kr.co.vividnext.sodalive.v2.main.home.model.HomeRecommendationCreatorUiModel
|
||||||
|
import kr.co.vividnext.sodalive.v2.main.home.model.HomeRecommendationFirstAudioContentSection
|
||||||
|
import kr.co.vividnext.sodalive.v2.main.home.model.HomeRecommendationFirstAudioContentUiModel
|
||||||
|
import kr.co.vividnext.sodalive.v2.main.home.model.HomeRecommendationGenreCreatorGroupUiModel
|
||||||
|
import kr.co.vividnext.sodalive.v2.main.home.model.HomeRecommendationGenreCreatorSection
|
||||||
|
import kr.co.vividnext.sodalive.v2.main.home.model.HomeRecommendationLiveSection
|
||||||
|
import kr.co.vividnext.sodalive.v2.main.home.model.HomeRecommendationLiveUiModel
|
||||||
|
import kr.co.vividnext.sodalive.v2.main.home.model.HomeRecommendationPopularCommunityPostSection
|
||||||
|
import kr.co.vividnext.sodalive.v2.main.home.model.HomeRecommendationRecentlyActiveCreatorSection
|
||||||
|
import kr.co.vividnext.sodalive.v2.main.home.model.HomeRecommendationRecentlyActiveCreatorUiModel
|
||||||
|
import kr.co.vividnext.sodalive.v2.main.home.model.HomeRecommendationRecentDebutCreatorSection
|
||||||
|
import kr.co.vividnext.sodalive.v2.main.home.model.HomeRecommendationUiState
|
||||||
|
import kr.co.vividnext.sodalive.v2.main.home.model.RecommendedActivityType
|
||||||
|
import kr.co.vividnext.sodalive.v2.main.home.ui.HomeAiCharacterAdapter
|
||||||
|
import kr.co.vividnext.sodalive.v2.main.home.ui.HomeBannerBinder
|
||||||
|
import kr.co.vividnext.sodalive.v2.main.home.ui.HomeCheerCreatorAdapter
|
||||||
|
import kr.co.vividnext.sodalive.v2.main.home.ui.HomeFirstAudioAdapter
|
||||||
|
import kr.co.vividnext.sodalive.v2.main.home.ui.HomeFollowAllButtonBinder
|
||||||
|
import kr.co.vividnext.sodalive.v2.main.home.ui.HomeGenreCreatorAdapter
|
||||||
|
import kr.co.vividnext.sodalive.v2.main.home.ui.HomeLiveAdapter
|
||||||
|
import kr.co.vividnext.sodalive.v2.main.home.ui.HomeRecentActivityCreatorAdapter
|
||||||
|
import kr.co.vividnext.sodalive.v2.main.home.ui.HomeRecentDebutCreatorAdapter
|
||||||
|
import kr.co.vividnext.sodalive.v2.widget.AudioContentTag
|
||||||
|
import kr.co.vividnext.sodalive.v2.widget.characterchatthumbnail.CharacterChatThumbnailItem
|
||||||
|
|
||||||
class HomeMainFragment : BaseFragment<FragmentV2MainHomeBinding>(
|
class HomeMainFragment : BaseFragment<FragmentV2MainHomeBinding>(
|
||||||
FragmentV2MainHomeBinding::inflate
|
FragmentV2MainHomeBinding::inflate
|
||||||
) {
|
) {
|
||||||
|
private val liveAdapter = HomeLiveAdapter()
|
||||||
|
private val recentActivityCreatorAdapter = HomeRecentActivityCreatorAdapter()
|
||||||
|
private val recentDebutCreatorAdapter = HomeRecentDebutCreatorAdapter()
|
||||||
|
private val firstAudioAdapter = HomeFirstAudioAdapter()
|
||||||
|
private val aiCharacterAdapter = HomeAiCharacterAdapter()
|
||||||
|
private val genreCreatorAdapter = HomeGenreCreatorAdapter()
|
||||||
|
private val cheerCreatorAdapter = HomeCheerCreatorAdapter()
|
||||||
|
private var bannerBinder: HomeBannerBinder? = null
|
||||||
|
private var onGenreFollowAllClick: (List<Long>) -> Unit = {}
|
||||||
|
private var onCheerFollowAllClick: (List<Long>) -> Unit = {}
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
@@ -23,6 +63,99 @@ class HomeMainFragment : BaseFragment<FragmentV2MainHomeBinding>(
|
|||||||
)
|
)
|
||||||
binding.textTabBarHome.root.setOnTabSelectedListener { }
|
binding.textTabBarHome.root.setOnTabSelectedListener { }
|
||||||
setUpSectionTitles()
|
setUpSectionTitles()
|
||||||
|
setUpRecommendationAdapters()
|
||||||
|
bindHomeRecommendationContent(phase6SampleContent())
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setUpRecommendationAdapters() {
|
||||||
|
bannerBinder = HomeBannerBinder(binding.rvHomeBanners)
|
||||||
|
binding.rvHomeLives.adapter = liveAdapter
|
||||||
|
binding.rvHomeRecentActivityCreators.adapter = recentActivityCreatorAdapter
|
||||||
|
binding.rvHomeRecentDebutCreators.adapter = recentDebutCreatorAdapter
|
||||||
|
binding.rvHomeFirstAudioContents.adapter = firstAudioAdapter
|
||||||
|
binding.rvHomeAiCharacters.adapter = aiCharacterAdapter
|
||||||
|
binding.rvHomeGenreCreators.apply {
|
||||||
|
layoutManager = LinearLayoutManager(requireContext(), LinearLayoutManager.HORIZONTAL, false)
|
||||||
|
adapter = genreCreatorAdapter
|
||||||
|
}
|
||||||
|
binding.rvHomeCheerCreators.apply {
|
||||||
|
layoutManager = LinearLayoutManager(requireContext(), LinearLayoutManager.HORIZONTAL, false)
|
||||||
|
adapter = cheerCreatorAdapter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun bindHomeRecommendationContent(content: HomeRecommendationUiState.Content) {
|
||||||
|
bindLiveSection(content.lives)
|
||||||
|
bindBannerSection(content.banners)
|
||||||
|
bindRecentActivitySection(content.recentlyActiveCreators)
|
||||||
|
bindRecentDebutSection(content.recentDebutCreators)
|
||||||
|
bindFirstAudioSection(content.firstAudioContents)
|
||||||
|
bindAiCharacterSection(content.aiCharacters)
|
||||||
|
bindGenreCreatorSection(content.genreCreators)
|
||||||
|
bindCheerCreatorSection(content.cheerCreators)
|
||||||
|
bindPopularCommunitySection(content.popularCommunityPosts)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun bindLiveSection(section: HomeRecommendationLiveSection) {
|
||||||
|
binding.llHomeLiveSection.visibility = section.items.toSectionVisibility()
|
||||||
|
liveAdapter.submitItems(section.items)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun bindBannerSection(section: HomeRecommendationBannerSection) {
|
||||||
|
binding.llHomeBannerSection.visibility = section.items.toSectionVisibility()
|
||||||
|
bannerBinder?.bind(section)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun bindRecentActivitySection(section: HomeRecommendationRecentlyActiveCreatorSection) {
|
||||||
|
binding.llHomeRecentActivitySection.visibility = section.items.toSectionVisibility()
|
||||||
|
recentActivityCreatorAdapter.submitItems(section.items)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun bindRecentDebutSection(section: HomeRecommendationRecentDebutCreatorSection) {
|
||||||
|
binding.llHomeRecentDebutSection.visibility = section.items.toSectionVisibility()
|
||||||
|
recentDebutCreatorAdapter.submitItems(section.items)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun bindFirstAudioSection(section: HomeRecommendationFirstAudioContentSection) {
|
||||||
|
binding.llHomeFirstAudioSection.visibility = section.items.toSectionVisibility()
|
||||||
|
firstAudioAdapter.submitItems(section.items)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun bindAiCharacterSection(section: HomeRecommendationAiCharacterSection) {
|
||||||
|
binding.llHomeAiCharacterSection.visibility = section.items.toSectionVisibility()
|
||||||
|
aiCharacterAdapter.submitItems(section.items)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun bindGenreCreatorSection(section: HomeRecommendationGenreCreatorSection) {
|
||||||
|
val group = section.groups.firstOrNull { it.creators.isNotEmpty() }
|
||||||
|
binding.llHomeGenreCreatorSection.visibility = if (group == null) View.GONE else View.VISIBLE
|
||||||
|
if (group == null) {
|
||||||
|
genreCreatorAdapter.submitItems(emptyList())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
binding.tvHomeGenreCreatorTitleGenre.text = group.genre
|
||||||
|
genreCreatorAdapter.submitItems(group.creators)
|
||||||
|
HomeFollowAllButtonBinder.bind(
|
||||||
|
view = binding.viewHomeGenreFollowAll.root,
|
||||||
|
creatorIds = group.creators.map { it.creatorId },
|
||||||
|
isFollowCompleted = group.isFollowCompleted,
|
||||||
|
onClick = onGenreFollowAllClick
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun bindCheerCreatorSection(section: HomeRecommendationCheerCreatorSection) {
|
||||||
|
binding.llHomeCheerCreatorSection.visibility = section.items.toSectionVisibility()
|
||||||
|
cheerCreatorAdapter.submitItems(section.items)
|
||||||
|
HomeFollowAllButtonBinder.bind(
|
||||||
|
view = binding.viewHomeCheerFollowAll.root,
|
||||||
|
creatorIds = section.items.map { it.creatorId },
|
||||||
|
isFollowCompleted = section.isFollowCompleted,
|
||||||
|
onClick = onCheerFollowAllClick
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun bindPopularCommunitySection(section: HomeRecommendationPopularCommunityPostSection) {
|
||||||
|
binding.llHomePopularCommunitySection.visibility = section.items.toSectionVisibility()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setUpSectionTitles() {
|
private fun setUpSectionTitles() {
|
||||||
@@ -56,4 +189,78 @@ class HomeMainFragment : BaseFragment<FragmentV2MainHomeBinding>(
|
|||||||
tvSectionTitle.setText(titleResId)
|
tvSectionTitle.setText(titleResId)
|
||||||
ivSectionTitleChevron.visibility = if (showMore) View.VISIBLE else View.GONE
|
ivSectionTitleChevron.visibility = if (showMore) View.VISIBLE else View.GONE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun List<*>.toSectionVisibility(): Int = if (isEmpty()) View.GONE else View.VISIBLE
|
||||||
|
|
||||||
|
private fun phase6SampleContent(): HomeRecommendationUiState.Content = HomeRecommendationUiState.Content(
|
||||||
|
lives = HomeRecommendationLiveSection(
|
||||||
|
listOf(
|
||||||
|
HomeRecommendationLiveUiModel(1L, 101L, null, "오늘 밤 라이브", "소다", "20:00"),
|
||||||
|
HomeRecommendationLiveUiModel(2L, 102L, null, "감성 낭독", "라임", "21:30"),
|
||||||
|
HomeRecommendationLiveUiModel(3L, 103L, null, "신작 토크", "하루", "22:00")
|
||||||
|
)
|
||||||
|
),
|
||||||
|
banners = HomeRecommendationBannerSection(
|
||||||
|
listOf(
|
||||||
|
HomeRecommendationBannerUiModel("sample-banner-1", null, null, null, null),
|
||||||
|
HomeRecommendationBannerUiModel("sample-banner-2", null, null, null, null)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
recentlyActiveCreators = HomeRecommendationRecentlyActiveCreatorSection(
|
||||||
|
listOf(
|
||||||
|
HomeRecommendationRecentlyActiveCreatorUiModel(
|
||||||
|
201L,
|
||||||
|
"베리",
|
||||||
|
null,
|
||||||
|
"LIVE_REPLAY도 라이브 라벨로 표시",
|
||||||
|
RecommendedActivityType.LiveReplay,
|
||||||
|
RecommendedActivityType.LiveReplay.labelResId,
|
||||||
|
"방금"
|
||||||
|
),
|
||||||
|
HomeRecommendationRecentlyActiveCreatorUiModel(202L, "모카", null, "알 수 없는 활동", null, null, "오늘")
|
||||||
|
)
|
||||||
|
),
|
||||||
|
recentDebutCreators = HomeRecommendationRecentDebutCreatorSection(sampleCreators(301L)),
|
||||||
|
firstAudioContents = HomeRecommendationFirstAudioContentSection(
|
||||||
|
listOf(
|
||||||
|
HomeRecommendationFirstAudioContentUiModel(
|
||||||
|
contentId = 401L,
|
||||||
|
creatorId = 301L,
|
||||||
|
creatorNickname = "아린",
|
||||||
|
creatorProfileImage = null,
|
||||||
|
title = "처음 공개하는 오디오",
|
||||||
|
price = 0,
|
||||||
|
coverImage = null,
|
||||||
|
releaseDate = "2026.06.02",
|
||||||
|
tags = setOf(AudioContentTag.First, AudioContentTag.Point, AudioContentTag.Free)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
aiCharacters = HomeRecommendationAiCharacterSection(
|
||||||
|
listOf(
|
||||||
|
HomeRecommendationAiCharacterUiModel(
|
||||||
|
CharacterChatThumbnailItem(
|
||||||
|
characterId = 501L,
|
||||||
|
imageUrl = "",
|
||||||
|
characterName = "레아",
|
||||||
|
characterDescription = "밤마다 이야기를 들려주는 AI 캐릭터",
|
||||||
|
chatMessageCount = 14000L,
|
||||||
|
hasOriginal = true,
|
||||||
|
originalTitle = "달빛 아래"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
genreCreators = HomeRecommendationGenreCreatorSection(
|
||||||
|
listOf(HomeRecommendationGenreCreatorGroupUiModel("로맨스", sampleCreators(601L)))
|
||||||
|
),
|
||||||
|
cheerCreators = HomeRecommendationCheerCreatorSection(sampleCreators(701L)),
|
||||||
|
popularCommunityPosts = HomeRecommendationPopularCommunityPostSection(emptyList())
|
||||||
|
)
|
||||||
|
|
||||||
|
private fun sampleCreators(startId: Long): List<HomeRecommendationCreatorUiModel> = listOf(
|
||||||
|
HomeRecommendationCreatorUiModel(startId, "아린", null),
|
||||||
|
HomeRecommendationCreatorUiModel(startId + 1, "유나", null),
|
||||||
|
HomeRecommendationCreatorUiModel(startId + 2, "세이", null)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,313 @@
|
|||||||
|
package kr.co.vividnext.sodalive.v2.main.home.ui
|
||||||
|
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.ImageView
|
||||||
|
import android.widget.TextView
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import kr.co.vividnext.sodalive.R
|
||||||
|
import kr.co.vividnext.sodalive.extensions.loadUrl
|
||||||
|
import kr.co.vividnext.sodalive.v2.main.home.model.HomeRecommendationAiCharacterUiModel
|
||||||
|
import kr.co.vividnext.sodalive.v2.main.home.model.HomeRecommendationBannerSection
|
||||||
|
import kr.co.vividnext.sodalive.v2.main.home.model.HomeRecommendationCreatorUiModel
|
||||||
|
import kr.co.vividnext.sodalive.v2.main.home.model.HomeRecommendationFirstAudioContentUiModel
|
||||||
|
import kr.co.vividnext.sodalive.v2.main.home.model.HomeRecommendationLiveUiModel
|
||||||
|
import kr.co.vividnext.sodalive.v2.main.home.model.HomeRecommendationRecentlyActiveCreatorUiModel
|
||||||
|
import kr.co.vividnext.sodalive.v2.widget.AudioContentCardSize
|
||||||
|
import kr.co.vividnext.sodalive.v2.widget.AudioContentCardView
|
||||||
|
import kr.co.vividnext.sodalive.v2.widget.banner.BannerItem
|
||||||
|
import kr.co.vividnext.sodalive.v2.widget.banner.BannerView
|
||||||
|
import kr.co.vividnext.sodalive.v2.widget.characterchatthumbnail.CharacterChatThumbnailItem
|
||||||
|
import kr.co.vividnext.sodalive.v2.widget.characterchatthumbnail.CharacterChatThumbnailView
|
||||||
|
import kr.co.vividnext.sodalive.v2.widget.livethumbnail.LiveThumbnailItem
|
||||||
|
import kr.co.vividnext.sodalive.v2.widget.livethumbnail.LiveThumbnailSimpleView
|
||||||
|
|
||||||
|
class HomeLiveAdapter : RecyclerView.Adapter<HomeLiveAdapter.LiveViewHolder>() {
|
||||||
|
private var items: List<HomeRecommendationLiveUiModel> = emptyList()
|
||||||
|
private var onClick: ((HomeRecommendationLiveUiModel) -> Unit)? = null
|
||||||
|
|
||||||
|
fun submitItems(items: List<HomeRecommendationLiveUiModel>) {
|
||||||
|
this.items = items
|
||||||
|
notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setOnLiveClick(listener: ((HomeRecommendationLiveUiModel) -> Unit)?) {
|
||||||
|
onClick = listener
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): LiveViewHolder {
|
||||||
|
val view = LayoutInflater.from(parent.context).inflate(R.layout.view_live_thumbnail_simple, parent, false)
|
||||||
|
view.layoutParams = RecyclerView.LayoutParams(
|
||||||
|
ViewGroup.LayoutParams.WRAP_CONTENT,
|
||||||
|
ViewGroup.LayoutParams.WRAP_CONTENT
|
||||||
|
).apply { marginEnd = parent.resources.getDimensionPixelSize(R.dimen.spacing_12) }
|
||||||
|
return LiveViewHolder(view as LiveThumbnailSimpleView)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBindViewHolder(holder: LiveViewHolder, position: Int) {
|
||||||
|
holder.bind(items[position], onClick)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getItemCount(): Int = items.size
|
||||||
|
|
||||||
|
class LiveViewHolder(
|
||||||
|
private val view: LiveThumbnailSimpleView
|
||||||
|
) : RecyclerView.ViewHolder(view) {
|
||||||
|
fun bind(
|
||||||
|
item: HomeRecommendationLiveUiModel,
|
||||||
|
onClick: ((HomeRecommendationLiveUiModel) -> Unit)?
|
||||||
|
) {
|
||||||
|
val thumbnailItem = LiveThumbnailItem(
|
||||||
|
liveId = item.liveId,
|
||||||
|
creatorId = item.creatorId,
|
||||||
|
imageUrl = item.imageUrl.orEmpty(),
|
||||||
|
title = item.title,
|
||||||
|
creatorName = item.creatorNickname,
|
||||||
|
liveStartTimeText = item.beginDateTime.orEmpty()
|
||||||
|
)
|
||||||
|
view.bind(thumbnailItem)
|
||||||
|
view.imageView().loadUrl(item.imageUrl)
|
||||||
|
view.setOnLiveThumbnailClick(if (onClick == null) null else { _: LiveThumbnailItem -> onClick.invoke(item) })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class HomeBannerBinder(
|
||||||
|
private val bannerView: BannerView
|
||||||
|
) {
|
||||||
|
private var sourceItems: List<kr.co.vividnext.sodalive.v2.main.home.model.HomeRecommendationBannerUiModel> = emptyList()
|
||||||
|
private var onBannerClick: ((kr.co.vividnext.sodalive.v2.main.home.model.HomeRecommendationBannerUiModel) -> Unit)? = null
|
||||||
|
|
||||||
|
init {
|
||||||
|
bannerView.setOnBindBannerImage { imageView, item -> imageView.loadUrl(item.imageUrl) }
|
||||||
|
bannerView.setOnBannerClickListener { bannerItem ->
|
||||||
|
sourceItems.firstOrNull { it.bannerId == bannerItem.bannerId }?.let { onBannerClick?.invoke(it) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setOnBannerClick(listener: ((kr.co.vividnext.sodalive.v2.main.home.model.HomeRecommendationBannerUiModel) -> Unit)?) {
|
||||||
|
onBannerClick = listener
|
||||||
|
}
|
||||||
|
|
||||||
|
fun bind(section: HomeRecommendationBannerSection) {
|
||||||
|
sourceItems = section.items
|
||||||
|
bannerView.setItems(
|
||||||
|
section.items.map { item ->
|
||||||
|
BannerItem(
|
||||||
|
bannerId = item.bannerId,
|
||||||
|
imageUrl = item.imageUrl.orEmpty()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class HomeRecentActivityCreatorAdapter : RecyclerView.Adapter<HomeRecentActivityCreatorAdapter.CreatorViewHolder>() {
|
||||||
|
private var items: List<HomeRecommendationRecentlyActiveCreatorUiModel> = emptyList()
|
||||||
|
|
||||||
|
fun submitItems(items: List<HomeRecommendationRecentlyActiveCreatorUiModel>) {
|
||||||
|
this.items = items
|
||||||
|
notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CreatorViewHolder {
|
||||||
|
val view = LayoutInflater.from(parent.context).inflate(R.layout.item_home_recent_activity_creator, parent, false)
|
||||||
|
view.layoutParams = recyclerItemLayoutParams(parent)
|
||||||
|
return CreatorViewHolder(view)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBindViewHolder(holder: CreatorViewHolder, position: Int) {
|
||||||
|
holder.bind(items[position])
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getItemCount(): Int = items.size
|
||||||
|
|
||||||
|
class CreatorViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
||||||
|
private val profileImage = itemView.findViewById<ImageView>(R.id.iv_home_recent_activity_creator_profile)
|
||||||
|
private val activityTypeText = itemView.findViewById<TextView>(R.id.tv_home_recent_activity_type)
|
||||||
|
private val titleText = itemView.findViewById<TextView>(R.id.tv_home_recent_activity_title)
|
||||||
|
private val nicknameText = itemView.findViewById<TextView>(R.id.tv_home_recent_activity_nickname)
|
||||||
|
|
||||||
|
fun bind(item: HomeRecommendationRecentlyActiveCreatorUiModel) {
|
||||||
|
profileImage.loadUrl(item.profileImage)
|
||||||
|
item.activityLabelResId?.let { labelResId ->
|
||||||
|
activityTypeText.setText(labelResId)
|
||||||
|
activityTypeText.visibility = View.VISIBLE
|
||||||
|
} ?: run {
|
||||||
|
activityTypeText.visibility = View.GONE
|
||||||
|
}
|
||||||
|
titleText.text = item.activityAt.orEmpty()
|
||||||
|
titleText.visibility = if (item.activityAt.isNullOrBlank()) View.GONE else View.VISIBLE
|
||||||
|
nicknameText.text = item.nickname
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class HomeRecentDebutCreatorAdapter : RecyclerView.Adapter<HomeRecentDebutCreatorAdapter.CreatorViewHolder>() {
|
||||||
|
private var items: List<HomeRecommendationCreatorUiModel> = emptyList()
|
||||||
|
|
||||||
|
fun submitItems(items: List<HomeRecommendationCreatorUiModel>) {
|
||||||
|
this.items = items
|
||||||
|
notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CreatorViewHolder {
|
||||||
|
val view = LayoutInflater.from(parent.context).inflate(R.layout.item_home_recent_debut_creator, parent, false)
|
||||||
|
view.layoutParams = recyclerItemLayoutParams(parent)
|
||||||
|
return CreatorViewHolder(view)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBindViewHolder(holder: CreatorViewHolder, position: Int) {
|
||||||
|
holder.bind(items[position])
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getItemCount(): Int = items.size
|
||||||
|
|
||||||
|
class CreatorViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
||||||
|
private val profileImage = itemView.findViewById<ImageView>(R.id.iv_home_recent_debut_creator_profile)
|
||||||
|
private val nicknameText = itemView.findViewById<TextView>(R.id.tv_home_recent_debut_creator_nickname)
|
||||||
|
|
||||||
|
fun bind(item: HomeRecommendationCreatorUiModel) {
|
||||||
|
profileImage.loadUrl(item.profileImage)
|
||||||
|
nicknameText.text = item.nickname
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class HomeFirstAudioAdapter : RecyclerView.Adapter<HomeFirstAudioAdapter.AudioViewHolder>() {
|
||||||
|
private var items: List<HomeRecommendationFirstAudioContentUiModel> = emptyList()
|
||||||
|
|
||||||
|
fun submitItems(items: List<HomeRecommendationFirstAudioContentUiModel>) {
|
||||||
|
this.items = items
|
||||||
|
notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AudioViewHolder {
|
||||||
|
val view = LayoutInflater.from(parent.context).inflate(
|
||||||
|
R.layout.view_audio_content_card,
|
||||||
|
parent,
|
||||||
|
false
|
||||||
|
) as AudioContentCardView
|
||||||
|
view.layoutParams = recyclerItemLayoutParams(parent)
|
||||||
|
return AudioViewHolder(view)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBindViewHolder(holder: AudioViewHolder, position: Int) {
|
||||||
|
holder.bind(items[position])
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getItemCount(): Int = items.size
|
||||||
|
|
||||||
|
class AudioViewHolder(
|
||||||
|
private val view: AudioContentCardView
|
||||||
|
) : RecyclerView.ViewHolder(view) {
|
||||||
|
fun bind(item: HomeRecommendationFirstAudioContentUiModel) {
|
||||||
|
view.setSize(AudioContentCardSize.Medium)
|
||||||
|
view.setContent(item.title, item.creatorNickname)
|
||||||
|
view.thumbnailView().loadUrl(item.coverImage)
|
||||||
|
view.setTags(item.tags)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class HomeAiCharacterAdapter : RecyclerView.Adapter<HomeAiCharacterAdapter.CharacterViewHolder>() {
|
||||||
|
private var items: List<HomeRecommendationAiCharacterUiModel> = emptyList()
|
||||||
|
|
||||||
|
fun submitItems(items: List<HomeRecommendationAiCharacterUiModel>) {
|
||||||
|
this.items = items
|
||||||
|
notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CharacterViewHolder {
|
||||||
|
val view = LayoutInflater.from(parent.context).inflate(
|
||||||
|
R.layout.view_character_chat_thumbnail,
|
||||||
|
parent,
|
||||||
|
false
|
||||||
|
) as CharacterChatThumbnailView
|
||||||
|
view.layoutParams = recyclerItemLayoutParams(parent)
|
||||||
|
return CharacterViewHolder(view)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBindViewHolder(holder: CharacterViewHolder, position: Int) {
|
||||||
|
holder.bind(items[position].item)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getItemCount(): Int = items.size
|
||||||
|
|
||||||
|
class CharacterViewHolder(
|
||||||
|
private val view: CharacterChatThumbnailView
|
||||||
|
) : RecyclerView.ViewHolder(view) {
|
||||||
|
fun bind(item: CharacterChatThumbnailItem) {
|
||||||
|
view.bind(item)
|
||||||
|
view.imageView().loadUrl(item.imageUrl)
|
||||||
|
view.setOnCharacterClick(null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class HomeGenreCreatorAdapter : HomeCreatorProfileAdapter()
|
||||||
|
|
||||||
|
class HomeCheerCreatorAdapter : HomeCreatorProfileAdapter()
|
||||||
|
|
||||||
|
open class HomeCreatorProfileAdapter : RecyclerView.Adapter<HomeCreatorProfileAdapter.CreatorViewHolder>() {
|
||||||
|
private var items: List<HomeRecommendationCreatorUiModel> = emptyList()
|
||||||
|
|
||||||
|
fun submitItems(items: List<HomeRecommendationCreatorUiModel>) {
|
||||||
|
this.items = items
|
||||||
|
notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CreatorViewHolder {
|
||||||
|
val view = LayoutInflater.from(parent.context).inflate(R.layout.item_home_creator_profile, parent, false)
|
||||||
|
view.layoutParams = recyclerItemLayoutParams(parent)
|
||||||
|
return CreatorViewHolder(view)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBindViewHolder(holder: CreatorViewHolder, position: Int) {
|
||||||
|
holder.bind(items[position])
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getItemCount(): Int = items.size
|
||||||
|
|
||||||
|
class CreatorViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
||||||
|
private val profileImage = itemView.findViewById<ImageView>(R.id.iv_home_creator_profile)
|
||||||
|
private val nicknameText = itemView.findViewById<TextView>(R.id.tv_home_creator_profile_nickname)
|
||||||
|
|
||||||
|
fun bind(item: HomeRecommendationCreatorUiModel) {
|
||||||
|
profileImage.loadUrl(item.profileImage)
|
||||||
|
nicknameText.text = item.nickname
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object HomeFollowAllButtonBinder {
|
||||||
|
fun bind(
|
||||||
|
view: View,
|
||||||
|
creatorIds: List<Long>,
|
||||||
|
isFollowCompleted: Boolean,
|
||||||
|
onClick: (List<Long>) -> Unit
|
||||||
|
) {
|
||||||
|
val icon = view.findViewById<ImageView>(R.id.iv_home_follow_all_icon)
|
||||||
|
val text = view.findViewById<TextView>(R.id.tv_home_follow_all)
|
||||||
|
icon.setImageResource(if (isFollowCompleted) R.drawable.ic_new_following else R.drawable.ic_new_follow)
|
||||||
|
text.setText(
|
||||||
|
if (isFollowCompleted) {
|
||||||
|
R.string.home_recommendation_follow_all_done
|
||||||
|
} else {
|
||||||
|
R.string.home_recommendation_follow_all
|
||||||
|
}
|
||||||
|
)
|
||||||
|
view.isEnabled = !isFollowCompleted
|
||||||
|
view.setOnClickListener {
|
||||||
|
if (creatorIds.isNotEmpty()) onClick(creatorIds)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun recyclerItemLayoutParams(parent: ViewGroup): RecyclerView.LayoutParams {
|
||||||
|
return RecyclerView.LayoutParams(
|
||||||
|
ViewGroup.LayoutParams.WRAP_CONTENT,
|
||||||
|
ViewGroup.LayoutParams.WRAP_CONTENT
|
||||||
|
).apply { marginEnd = parent.resources.getDimensionPixelSize(R.dimen.spacing_12) }
|
||||||
|
}
|
||||||
@@ -65,13 +65,10 @@
|
|||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:paddingTop="@dimen/spacing_24">
|
android:paddingTop="@dimen/spacing_24">
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<kr.co.vividnext.sodalive.v2.widget.banner.BannerView
|
||||||
android:id="@+id/rv_home_banners"
|
android:id="@+id/rv_home_banners"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="160dp"
|
android:layout_height="wrap_content" />
|
||||||
android:orientation="horizontal"
|
|
||||||
android:paddingHorizontal="@dimen/spacing_20"
|
|
||||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
@@ -193,6 +190,10 @@
|
|||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
android:paddingHorizontal="@dimen/spacing_20"
|
android:paddingHorizontal="@dimen/spacing_20"
|
||||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
|
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
|
||||||
|
|
||||||
|
<include
|
||||||
|
android:id="@+id/view_home_genre_follow_all"
|
||||||
|
layout="@layout/view_home_follow_all_button" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
@@ -213,6 +214,10 @@
|
|||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
android:paddingHorizontal="@dimen/spacing_20"
|
android:paddingHorizontal="@dimen/spacing_20"
|
||||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
|
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
|
||||||
|
|
||||||
|
<include
|
||||||
|
android:id="@+id/view_home_cheer_follow_all"
|
||||||
|
layout="@layout/view_home_follow_all_button" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
@@ -220,7 +225,8 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:paddingTop="@dimen/spacing_24">
|
android:paddingTop="@dimen/spacing_24"
|
||||||
|
android:visibility="gone">
|
||||||
|
|
||||||
<include
|
<include
|
||||||
android:id="@+id/view_home_popular_community_title"
|
android:id="@+id/view_home_popular_community_title"
|
||||||
|
|||||||
Reference in New Issue
Block a user