하트 랭킹 추가

This commit is contained in:
klaus 2024-11-12 00:32:21 +09:00
parent c15e9c203e
commit 3136b47838
9 changed files with 523 additions and 0 deletions

View File

@ -24,6 +24,7 @@ import kr.co.vividnext.sodalive.live.room.donation.LiveRoomDonationRequest
import kr.co.vividnext.sodalive.live.room.donation.LiveRoomDonationResponse
import kr.co.vividnext.sodalive.live.room.info.GetRoomInfoResponse
import kr.co.vividnext.sodalive.live.room.kick_out.LiveRoomKickOutRequest
import kr.co.vividnext.sodalive.live.room.like.GetLiveRoomHeartListResponse
import kr.co.vividnext.sodalive.live.room.like.GetLiveRoomHeartTotalResponse
import kr.co.vividnext.sodalive.live.room.like.LiveRoomLikeHeartRequest
import kr.co.vividnext.sodalive.live.room.profile.GetLiveRoomUserProfileResponse
@ -226,4 +227,10 @@ interface LiveApi {
@Path("id") id: Long,
@Header("Authorization") authHeader: String
): Single<ApiResponse<GetLiveRoomHeartTotalResponse>>
@GET("/live/room/{id}/heart-list")
fun heartStatus(
@Path("id") id: Long,
@Header("Authorization") authHeader: String
): Single<ApiResponse<GetLiveRoomHeartListResponse>>
}

View File

@ -256,4 +256,9 @@ class LiveRepository(
roomId,
authHeader = token
)
fun heartStatus(roomId: Long, token: String) = api.heartStatus(
roomId,
authHeader = token
)
}

View File

@ -87,6 +87,7 @@ import kr.co.vividnext.sodalive.live.room.donation.LiveRoomDonationMessageViewMo
import kr.co.vividnext.sodalive.live.room.donation.LiveRoomDonationRankingDialog
import kr.co.vividnext.sodalive.live.room.donation.LiveRoomDonationResponse
import kr.co.vividnext.sodalive.live.room.info.GetRoomInfoResponse
import kr.co.vividnext.sodalive.live.room.like.LiveRoomHeartRankingDialog
import kr.co.vividnext.sodalive.live.room.profile.LiveRoomProfileDialog
import kr.co.vividnext.sodalive.live.room.profile.LiveRoomProfileListAdapter
import kr.co.vividnext.sodalive.live.room.profile.LiveRoomUserProfileDialog
@ -538,6 +539,13 @@ class LiveRoomActivity : BaseActivity<ActivityLiveRoomBinding>(ActivityLiveRoomB
roomId = roomId
).show()
}
binding.llHeart.setOnClickListener {
LiveRoomHeartRankingDialog(
activity = this,
layoutInflater = layoutInflater,
getHeartRanking = { viewModel.heartStatus(roomId, it) }
).show()
}
setupChatAdapter()
setupSpeakerListAdapter()

View File

@ -21,6 +21,7 @@ import kr.co.vividnext.sodalive.live.LiveRepository
import kr.co.vividnext.sodalive.live.room.donation.GetLiveRoomDonationStatusResponse
import kr.co.vividnext.sodalive.live.room.donation.LiveRoomDonationResponse
import kr.co.vividnext.sodalive.live.room.info.GetRoomInfoResponse
import kr.co.vividnext.sodalive.live.room.like.GetLiveRoomHeartListResponse
import kr.co.vividnext.sodalive.live.room.menu.GetMenuPresetResponse
import kr.co.vividnext.sodalive.live.room.profile.GetLiveRoomUserProfileResponse
import kr.co.vividnext.sodalive.live.room.update.EditLiveRoomInfoRequest
@ -716,6 +717,34 @@ class LiveRoomViewModel(
)
}
fun heartStatus(roomId: Long, onSuccess: (GetLiveRoomHeartListResponse) -> Unit) {
_isLoading.value = true
compositeDisposable.add(
repository.heartStatus(roomId, token = "Bearer ${SharedPreferenceManager.token}")
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
{
_isLoading.value = false
if (it.success && it.data != null) {
onSuccess(it.data)
} else {
_toastLiveData.postValue(
"하트 현황을 가져오지 못했습니다\n다시 시도해 주세요."
)
}
},
{
_isLoading.value = false
it.message?.let { message -> Logger.e(message) }
_toastLiveData.postValue(
"하트 현황을 가져오지 못했습니다\n다시 시도해 주세요."
)
}
)
)
}
fun getUserRank(userId: Long): Int {
// 방장 -> -2
// 스탭 -> -3

View File

@ -0,0 +1,18 @@
package kr.co.vividnext.sodalive.live.room.like
import androidx.annotation.Keep
import com.google.gson.annotations.SerializedName
@Keep
data class GetLiveRoomHeartListResponse(
@SerializedName("heartList") val heartList: List<GetLiveRoomHeartListItem>,
@SerializedName("totalCount") val totalCount: Int,
@SerializedName("totalHeart") val totalHeart: Int
)
@Keep
data class GetLiveRoomHeartListItem(
@SerializedName("profileImage") val profileImage: String,
@SerializedName("nickname") val nickname: String,
@SerializedName("heart") val heart: Int
)

View File

@ -0,0 +1,144 @@
package kr.co.vividnext.sodalive.live.room.like
import android.annotation.SuppressLint
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.RecyclerView
import coil.load
import coil.transform.CircleCropTransformation
import kr.co.vividnext.sodalive.R
import kr.co.vividnext.sodalive.databinding.ItemLiveRoomHeartRankingBinding
import kr.co.vividnext.sodalive.extensions.dpToPx
import kr.co.vividnext.sodalive.extensions.moneyFormat
class LiveRoomHeartRankingAdapter :
RecyclerView.Adapter<LiveRoomHeartRankingAdapter.ViewHolder>() {
val items = mutableListOf<GetLiveRoomHeartListItem>()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ViewHolder(
parent.context,
ItemLiveRoomHeartRankingBinding.inflate(
LayoutInflater.from(parent.context),
parent,
false
)
)
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bind(items[position], position)
}
override fun getItemCount() = items.count()
inner class ViewHolder(
private val context: Context,
private val binding: ItemLiveRoomHeartRankingBinding
) : RecyclerView.ViewHolder(binding.root) {
@SuppressLint("SetTextI18n")
fun bind(item: GetLiveRoomHeartListItem, position: Int) {
binding.tvRank.text = "${position + 1}"
binding.tvNickname.text = item.nickname
binding.tvHeart.text = item.heart.moneyFormat()
binding.ivProfile.load(item.profileImage) {
crossfade(true)
placeholder(R.drawable.ic_place_holder)
transformations(CircleCropTransformation())
}
val lp = binding.rlHeartRanking.layoutParams as FrameLayout.LayoutParams
when (position) {
0 -> {
binding.ivBg.setImageResource(R.drawable.bg_circle_ffdc00_ffb600)
binding.ivBg.visibility = View.VISIBLE
binding.ivCrown.setImageResource(R.drawable.ic_crown_1)
binding.ivCrown.visibility = View.VISIBLE
binding.root.setBackgroundResource(
if (items.size == 1) {
R.drawable.bg_round_corner_4_7_13181b
} else {
R.drawable.bg_top_round_corner_4_7_13181b
}
)
lp.setMargins(
0,
20.dpToPx().toInt(),
0,
if (items.size == 1) {
20.dpToPx().toInt()
} else {
13.3f.dpToPx().toInt()
}
)
binding.rlHeartRanking.layoutParams = lp
}
1 -> {
binding.ivBg.setImageResource(R.drawable.bg_circle_ffffff_9f9f9f)
binding.ivBg.visibility = View.VISIBLE
binding.ivCrown.setImageResource(R.drawable.ic_crown_2)
binding.ivCrown.visibility = View.VISIBLE
if (items.size == 2) {
binding.root.setBackgroundResource(
R.drawable.bg_bottom_round_corner_4_7_13181b
)
} else {
binding.root.setBackgroundColor(
ContextCompat.getColor(context, R.color.color_13181b)
)
}
lp.setMargins(
0,
0,
0,
if (items.size == 2) {
20.dpToPx().toInt()
} else {
13.3f.dpToPx().toInt()
}
)
binding.rlHeartRanking.layoutParams = lp
}
2 -> {
binding.ivBg.setImageResource(R.drawable.bg_circle_e6a77a_c67e4a)
binding.ivBg.visibility = View.VISIBLE
binding.ivCrown.setImageResource(R.drawable.ic_crown_3)
binding.ivCrown.visibility = View.VISIBLE
binding.root.setBackgroundResource(
R.drawable.bg_bottom_round_corner_4_7_13181b
)
lp.setMargins(
0,
0,
0,
20.dpToPx().toInt()
)
binding.rlHeartRanking.layoutParams = lp
}
else -> {
binding.ivBg.setImageResource(0)
binding.ivBg.visibility = View.GONE
binding.ivCrown.visibility = View.GONE
binding.root.setBackgroundResource(0)
binding.root.background = null
lp.setMargins(0, 0, 0, 0)
binding.rlHeartRanking.layoutParams = lp
}
}
}
}
}

View File

@ -0,0 +1,85 @@
package kr.co.vividnext.sodalive.live.room.like
import android.annotation.SuppressLint
import android.graphics.Rect
import android.view.LayoutInflater
import android.view.View
import androidx.fragment.app.FragmentActivity
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.bottomsheet.BottomSheetDialog
import kr.co.vividnext.sodalive.databinding.DialogLiveRoomHeartRankingBinding
import kr.co.vividnext.sodalive.extensions.dpToPx
import kr.co.vividnext.sodalive.extensions.moneyFormat
@SuppressLint("NotifyDataSetChanged")
class LiveRoomHeartRankingDialog(
private val activity: FragmentActivity,
layoutInflater: LayoutInflater,
getHeartRanking: ((GetLiveRoomHeartListResponse) -> Unit) -> Unit
) {
private val bottomSheetDialog: BottomSheetDialog = BottomSheetDialog(activity)
private val dialogView = DialogLiveRoomHeartRankingBinding.inflate(layoutInflater)
private val adapter = LiveRoomHeartRankingAdapter()
init {
bottomSheetDialog.setContentView(dialogView.root)
bottomSheetDialog.setCancelable(false)
dialogView.ivClose.setOnClickListener { bottomSheetDialog.dismiss() }
setupRecyclerView()
getHeartRanking {
adapter.items.clear()
adapter.items.addAll(it.heartList)
adapter.notifyDataSetChanged()
dialogView.tvTotalHeart.text = it.totalHeart.moneyFormat()
dialogView.tvTotalCount.text = it.totalCount.moneyFormat()
}
}
private fun setupRecyclerView() {
dialogView.rvHeartRanking.layoutManager = LinearLayoutManager(
activity,
LinearLayoutManager.VERTICAL,
false
)
dialogView.rvHeartRanking.addItemDecoration(object : RecyclerView.ItemDecoration() {
override fun getItemOffsets(
outRect: Rect,
view: View,
parent: RecyclerView,
state: RecyclerView.State
) {
super.getItemOffsets(outRect, view, parent, state)
outRect.left = 13.3f.dpToPx().toInt()
outRect.right = 13.3f.dpToPx().toInt()
when (parent.getChildAdapterPosition(view)) {
0, 1, 2 -> {
outRect.top = 0
outRect.bottom = 0
}
3 -> {
outRect.top = 20.dpToPx().toInt()
outRect.bottom = 6.7f.dpToPx().toInt()
}
else -> {
outRect.top = 6.7f.dpToPx().toInt()
outRect.bottom = 6.7f.dpToPx().toInt()
}
}
}
})
dialogView.rvHeartRanking.adapter = adapter
}
fun show() {
bottomSheetDialog.show()
}
}

View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/bg_top_round_corner_16_7_222222"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginTop="20dp"
android:fontFamily="@font/gmarket_sans_bold"
android:text="현재 라이브 하트랭킹"
android:textColor="@color/color_eeeeee"
android:textSize="16.7sp" />
<ImageView
android:id="@+id/iv_close"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:contentDescription="@null"
android:paddingHorizontal="20dp"
android:paddingVertical="18.7dp"
android:src="@drawable/ic_close_white" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/rl_total_can"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="13.3dp"
android:layout_marginTop="7.7dp"
android:background="@drawable/bg_round_corner_8_13181b"
android:paddingHorizontal="18.7dp"
android:paddingVertical="10.7dp">
<TextView
android:id="@+id/tv_total_heart_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/gmarket_sans_bold"
android:text="합계"
android:textColor="@color/color_d2d2d2"
android:textSize="13.3sp" />
<TextView
android:id="@+id/tv_total_heart"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="2.7dp"
android:layout_toStartOf="@+id/tv_total_can_unit"
android:layout_toEndOf="@+id/tv_total_heart_title"
android:fontFamily="@font/gmarket_sans_medium"
android:gravity="end"
android:textColor="@color/color_80d8ff"
android:textSize="14sp"
tools:text="1,999,999" />
<TextView
android:id="@+id/tv_total_can_unit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:fontFamily="@font/gmarket_sans_medium"
android:text="하트"
android:textColor="@color/color_bbbbbb"
android:textSize="10.7sp"
tools:ignore="SmallSp" />
</RelativeLayout>
<LinearLayout
android:id="@+id/ll_total_count"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="13.3dp"
android:layout_marginTop="13.3dp"
android:layout_marginBottom="8dp"
android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/gmarket_sans_medium"
android:text="전체"
android:textColor="@color/color_eeeeee"
android:textSize="14.7sp" />
<TextView
android:id="@+id/tv_total_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="6.7dp"
android:fontFamily="@font/gmarket_sans_medium"
android:textColor="@color/color_80d8ff"
android:textSize="12sp"
tools:text="56" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/gmarket_sans_medium"
android:text=" 명"
android:textColor="@color/color_777777"
android:textSize="12sp" />
</LinearLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_heart_ranking"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="none" />
</LinearLayout>

View File

@ -0,0 +1,107 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:background="@color/black">
<RelativeLayout
android:id="@+id/rl_heart_ranking"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:background="@color/black"
tools:ignore="UselessParent">
<TextView
android:id="@+id/tv_rank"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginStart="13.3dp"
android:ellipsize="end"
android:fontFamily="@font/gmarket_sans_bold"
android:maxLength="10"
android:textColor="@color/color_eeeeee"
android:textSize="13.3sp"
tools:text="1" />
<RelativeLayout
android:id="@+id/rl_profile"
android:layout_width="65dp"
android:layout_height="65dp"
android:layout_centerVertical="true"
android:layout_marginStart="13.3dp"
android:layout_toEndOf="@+id/tv_rank">
<ImageView
android:id="@+id/iv_bg"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:contentDescription="@null" />
<ImageView
android:id="@+id/iv_profile"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_centerInParent="true"
android:contentDescription="@null"
tools:src="@mipmap/ic_launcher" />
<ImageView
android:id="@+id/iv_crown"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentBottom="true"
android:contentDescription="@null" />
</RelativeLayout>
<TextView
android:id="@+id/tv_nickname"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginStart="13.3dp"
android:layout_toEndOf="@+id/rl_profile"
android:ellipsize="end"
android:fontFamily="@font/gmarket_sans_medium"
android:lines="1"
android:maxLength="12"
android:textColor="@color/color_eeeeee"
android:textSize="13.3sp"
tools:text="Remix" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:layout_marginHorizontal="13.3dp"
android:layout_toEndOf="@+id/tv_nickname"
android:gravity="end|center_vertical"
android:orientation="horizontal">
<TextView
android:id="@+id/tv_heart"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="4dp"
android:fontFamily="@font/gmarket_sans_medium"
android:gravity="end"
android:textColor="@color/color_3bb9f1"
android:textSize="13.3sp"
tools:text="1000" />
<TextView
android:id="@+id/tv_donation_can_unit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/gmarket_sans_medium"
android:gravity="end"
android:text="하트"
android:textColor="@color/color_eeeeee"
android:textSize="10.7sp"
tools:ignore="SmallSp" />
</LinearLayout>
</RelativeLayout>
</FrameLayout>