feat(creator): 후원 탭 어댑터를 추가한다

This commit is contained in:
2026-06-22 21:24:35 +09:00
parent 6c8d3dfc76
commit 77d889d9ab
2 changed files with 160 additions and 0 deletions

View File

@@ -0,0 +1,108 @@
package kr.co.vividnext.sodalive.v2.creator.channel.donation.ui
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import coil.transform.CircleCropTransformation
import kr.co.vividnext.sodalive.R
import kr.co.vividnext.sodalive.databinding.ItemCreatorChannelDonationBinding
import kr.co.vividnext.sodalive.databinding.ItemCreatorChannelDonationRankingBinding
import kr.co.vividnext.sodalive.extensions.loadUrl
import kr.co.vividnext.sodalive.extensions.moneyFormat
import kr.co.vividnext.sodalive.v2.creator.channel.donation.model.CreatorChannelDonationRankingUiModel
import kr.co.vividnext.sodalive.v2.creator.channel.donation.model.CreatorChannelDonationUiModel
class CreatorChannelDonationAdapter(
private val onRankingAllClick: () -> Unit = { }
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
private var items: List<CreatorChannelDonationListItem> = emptyList()
fun submitItems(
rankings: List<CreatorChannelDonationRankingUiModel>,
donations: List<CreatorChannelDonationUiModel>
) {
items = buildList {
if (rankings.isNotEmpty()) add(CreatorChannelDonationListItem.Ranking(rankings))
donations.forEach { add(CreatorChannelDonationListItem.Donation(it)) }
}
notifyDataSetChanged()
}
override fun getItemViewType(position: Int): Int = when (items[position]) {
is CreatorChannelDonationListItem.Ranking -> VIEW_TYPE_RANKING
is CreatorChannelDonationListItem.Donation -> VIEW_TYPE_DONATION
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return when (viewType) {
VIEW_TYPE_RANKING -> RankingViewHolder(
ItemCreatorChannelDonationRankingBinding.inflate(LayoutInflater.from(parent.context), parent, false),
onRankingAllClick
)
else -> DonationViewHolder(
ItemCreatorChannelDonationBinding.inflate(LayoutInflater.from(parent.context), parent, false)
)
}
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
when (val item = items[position]) {
is CreatorChannelDonationListItem.Ranking -> (holder as RankingViewHolder).bind(item.rankings)
is CreatorChannelDonationListItem.Donation -> (holder as DonationViewHolder).bind(item.donation)
}
}
override fun getItemCount(): Int = items.size
class RankingViewHolder(
private val binding: ItemCreatorChannelDonationRankingBinding,
private val onRankingAllClick: () -> Unit
) : RecyclerView.ViewHolder(binding.root) {
private val rankingAdapter = CreatorChannelDonationRankingAdapter()
init {
binding.rvCreatorChannelDonationRankingMembers.layoutManager = GridLayoutManager(itemView.context, 4)
binding.rvCreatorChannelDonationRankingMembers.adapter = rankingAdapter
binding.btnCreatorChannelDonationRankingAll.setOnClickListener { onRankingAllClick() }
}
fun bind(rankings: List<CreatorChannelDonationRankingUiModel>) {
rankingAdapter.submitItems(rankings)
}
}
class DonationViewHolder(
private val binding: ItemCreatorChannelDonationBinding
) : RecyclerView.ViewHolder(binding.root) {
fun bind(item: CreatorChannelDonationUiModel) = with(binding) {
layoutCreatorChannelDonationHeader.setBackgroundColor(root.context.getColor(item.headerColorResId))
ivCreatorChannelDonationProfile.loadUrl(item.profileImageUrl) {
crossfade(true)
placeholder(R.drawable.ic_placeholder_profile)
error(R.drawable.ic_placeholder_profile)
transformations(CircleCropTransformation())
}
tvCreatorChannelDonationNickname.text = item.nickname
tvCreatorChannelDonationCreatedAt.text = item.createdAtText
tvCreatorChannelDonationCan.text = root.context.getString(
R.string.creator_channel_donation_can_format,
item.can.moneyFormat()
)
tvCreatorChannelDonationMessage.text = item.message
}
}
companion object {
private const val VIEW_TYPE_RANKING = 0
private const val VIEW_TYPE_DONATION = 1
}
}
private sealed interface CreatorChannelDonationListItem {
data class Ranking(val rankings: List<CreatorChannelDonationRankingUiModel>) : CreatorChannelDonationListItem
data class Donation(val donation: CreatorChannelDonationUiModel) : CreatorChannelDonationListItem
}

View File

@@ -0,0 +1,52 @@
package kr.co.vividnext.sodalive.v2.creator.channel.donation.ui
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import coil.transform.CircleCropTransformation
import kr.co.vividnext.sodalive.R
import kr.co.vividnext.sodalive.databinding.ItemCreatorChannelDonationRankingMemberBinding
import kr.co.vividnext.sodalive.extensions.loadUrl
import kr.co.vividnext.sodalive.v2.creator.channel.donation.model.CreatorChannelDonationRankingUiModel
class CreatorChannelDonationRankingAdapter : RecyclerView.Adapter<CreatorChannelDonationRankingAdapter.ViewHolder>() {
private var items: List<CreatorChannelDonationRankingUiModel> = emptyList()
fun submitItems(items: List<CreatorChannelDonationRankingUiModel>) {
this.items = items.take(MAX_VISIBLE_RANKING_COUNT)
notifyDataSetChanged()
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder(
ItemCreatorChannelDonationRankingMemberBinding.inflate(LayoutInflater.from(parent.context), parent, false)
)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bind(items[position])
}
override fun getItemCount(): Int = items.size
class ViewHolder(
private val binding: ItemCreatorChannelDonationRankingMemberBinding
) : RecyclerView.ViewHolder(binding.root) {
fun bind(item: CreatorChannelDonationRankingUiModel) = with(binding) {
ivCreatorChannelDonationRankingProfile.loadUrl(item.profileImageUrl) {
crossfade(true)
placeholder(R.drawable.ic_placeholder_profile)
error(R.drawable.ic_placeholder_profile)
transformations(CircleCropTransformation())
}
tvCreatorChannelDonationRankingRank.text = item.rank.toString()
tvCreatorChannelDonationRankingNickname.text = item.nickname
}
}
companion object {
private const val MAX_VISIBLE_RANKING_COUNT = 8
}
}