feat(home): 보온 주간 차트 콘텐츠 정렬 기준 추가
- 매출, 판매량, 댓글 수, 좋아요 수
This commit is contained in:
@@ -0,0 +1,59 @@
|
|||||||
|
package kr.co.vividnext.sodalive.home
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import kr.co.vividnext.sodalive.R
|
||||||
|
import kr.co.vividnext.sodalive.databinding.ItemHomeContentThemeBinding
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 보온 주간 차트 정렬 선택 어댑터
|
||||||
|
* - 최신 콘텐츠 테마 선택 UI와 동일한 스타일 재사용
|
||||||
|
*/
|
||||||
|
class ContentRankingSortAdapter(
|
||||||
|
private val onClickSort: (ContentRankingSortType) -> Unit
|
||||||
|
) : RecyclerView.Adapter<ContentRankingSortAdapter.ViewHolder>() {
|
||||||
|
|
||||||
|
private val sorts = ContentRankingSortType.entries
|
||||||
|
private var selected: ContentRankingSortType = ContentRankingSortType.REVENUE
|
||||||
|
|
||||||
|
inner class ViewHolder(
|
||||||
|
private val binding: ItemHomeContentThemeBinding
|
||||||
|
) : RecyclerView.ViewHolder(binding.root) {
|
||||||
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
|
fun bind(type: ContentRankingSortType) {
|
||||||
|
binding.tvTheme.text = type.toKoreanLabel()
|
||||||
|
if (type == selected) {
|
||||||
|
binding.tvTheme.setBackgroundResource(R.drawable.bg_round_corner_999_3bb9f1)
|
||||||
|
} else {
|
||||||
|
binding.tvTheme.setBackgroundResource(R.drawable.bg_round_corner_999_263238)
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.root.setOnClickListener {
|
||||||
|
if (selected != type) {
|
||||||
|
selected = type
|
||||||
|
notifyDataSetChanged()
|
||||||
|
onClickSort(type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ViewHolder(
|
||||||
|
ItemHomeContentThemeBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||||
|
)
|
||||||
|
|
||||||
|
override fun getItemCount() = sorts.size
|
||||||
|
|
||||||
|
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||||
|
holder.bind(sorts[position])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun ContentRankingSortType.toKoreanLabel(): String = when (this) {
|
||||||
|
ContentRankingSortType.REVENUE -> "매출"
|
||||||
|
ContentRankingSortType.SALES_COUNT -> "판매량"
|
||||||
|
ContentRankingSortType.COMMENT_COUNT -> "댓글"
|
||||||
|
ContentRankingSortType.LIKE_COUNT -> "좋아요"
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package kr.co.vividnext.sodalive.home
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 콘텐츠 랭킹 정렬 기준
|
||||||
|
*/
|
||||||
|
enum class ContentRankingSortType {
|
||||||
|
// 매출
|
||||||
|
REVENUE,
|
||||||
|
|
||||||
|
// 판매량
|
||||||
|
SALES_COUNT,
|
||||||
|
|
||||||
|
// 댓글 수
|
||||||
|
COMMENT_COUNT,
|
||||||
|
|
||||||
|
// 좋아요 수
|
||||||
|
LIKE_COUNT
|
||||||
|
}
|
||||||
@@ -1,11 +1,13 @@
|
|||||||
package kr.co.vividnext.sodalive.home
|
package kr.co.vividnext.sodalive.home
|
||||||
|
|
||||||
import io.reactivex.rxjava3.core.Single
|
import io.reactivex.rxjava3.core.Single
|
||||||
|
import kr.co.vividnext.sodalive.audio_content.main.GetAudioContentRankingItem
|
||||||
import kr.co.vividnext.sodalive.audio_content.series.GetSeriesListResponse
|
import kr.co.vividnext.sodalive.audio_content.series.GetSeriesListResponse
|
||||||
import kr.co.vividnext.sodalive.common.ApiResponse
|
import kr.co.vividnext.sodalive.common.ApiResponse
|
||||||
import kr.co.vividnext.sodalive.settings.ContentType
|
import kr.co.vividnext.sodalive.settings.ContentType
|
||||||
import retrofit2.http.GET
|
import retrofit2.http.GET
|
||||||
import retrofit2.http.Header
|
import retrofit2.http.Header
|
||||||
|
import retrofit2.http.Path
|
||||||
import retrofit2.http.Query
|
import retrofit2.http.Query
|
||||||
|
|
||||||
interface HomeApi {
|
interface HomeApi {
|
||||||
@@ -39,4 +41,12 @@ interface HomeApi {
|
|||||||
@Query("contentType") contentType: ContentType,
|
@Query("contentType") contentType: ContentType,
|
||||||
@Header("Authorization") authHeader: String
|
@Header("Authorization") authHeader: String
|
||||||
): Single<ApiResponse<List<AudioContentMainItem>>>
|
): Single<ApiResponse<List<AudioContentMainItem>>>
|
||||||
|
|
||||||
|
@GET("/api/home/content-ranking")
|
||||||
|
fun getContentRankingBySort(
|
||||||
|
@Query("sort") sort: ContentRankingSortType,
|
||||||
|
@Query("isAdultContentVisible") isAdultContentVisible: Boolean,
|
||||||
|
@Query("contentType") contentType: ContentType,
|
||||||
|
@Header("Authorization") authHeader: String
|
||||||
|
): Single<ApiResponse<List<GetAudioContentRankingItem>>>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -869,6 +869,41 @@ class HomeFragment : BaseFragment<FragmentHomeBinding>(FragmentHomeBinding::infl
|
|||||||
)
|
)
|
||||||
binding.tvWeeklyChart.text = spSectionTitle
|
binding.tvWeeklyChart.text = spSectionTitle
|
||||||
|
|
||||||
|
// 정렬 선택 RecyclerView 설정
|
||||||
|
val sortAdapter = ContentRankingSortAdapter {
|
||||||
|
viewModel.getContentRanking(it)
|
||||||
|
}
|
||||||
|
binding.rvWeeklyChartSort.apply {
|
||||||
|
layoutManager = LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)
|
||||||
|
addItemDecoration(object : RecyclerView.ItemDecoration() {
|
||||||
|
override fun getItemOffsets(
|
||||||
|
outRect: Rect,
|
||||||
|
view: View,
|
||||||
|
parent: RecyclerView,
|
||||||
|
state: RecyclerView.State
|
||||||
|
) {
|
||||||
|
super.getItemOffsets(outRect, view, parent, state)
|
||||||
|
when (parent.getChildAdapterPosition(view)) {
|
||||||
|
0 -> {
|
||||||
|
outRect.left = 0
|
||||||
|
outRect.right = 8f.dpToPx().toInt()
|
||||||
|
}
|
||||||
|
|
||||||
|
sortAdapter.itemCount - 1 -> {
|
||||||
|
outRect.left = 8f.dpToPx().toInt()
|
||||||
|
outRect.right = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> {
|
||||||
|
outRect.left = 8f.dpToPx().toInt()
|
||||||
|
outRect.right = 8f.dpToPx().toInt()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
adapter = sortAdapter
|
||||||
|
}
|
||||||
|
|
||||||
weelyChartAdapter = HomeWeeklyChartAdapter(
|
weelyChartAdapter = HomeWeeklyChartAdapter(
|
||||||
width = screenWidth,
|
width = screenWidth,
|
||||||
onClickItem = {
|
onClickItem = {
|
||||||
@@ -935,12 +970,7 @@ class HomeFragment : BaseFragment<FragmentHomeBinding>(FragmentHomeBinding::infl
|
|||||||
recyclerView.adapter = weelyChartAdapter
|
recyclerView.adapter = weelyChartAdapter
|
||||||
|
|
||||||
viewModel.contentRankingLiveData.observe(viewLifecycleOwner) {
|
viewModel.contentRankingLiveData.observe(viewLifecycleOwner) {
|
||||||
if (it.isNotEmpty()) {
|
|
||||||
binding.llWeeklyChart.visibility = View.VISIBLE
|
|
||||||
weelyChartAdapter.addItems(it)
|
weelyChartAdapter.addItems(it)
|
||||||
} else {
|
|
||||||
binding.llWeeklyChart.visibility = View.GONE
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,4 +33,14 @@ class HomeRepository(private val api: HomeApi) {
|
|||||||
contentType = ContentType.entries[SharedPreferenceManager.contentPreference],
|
contentType = ContentType.entries[SharedPreferenceManager.contentPreference],
|
||||||
authHeader = token
|
authHeader = token
|
||||||
)
|
)
|
||||||
|
|
||||||
|
fun getContentRanking(
|
||||||
|
sortType: ContentRankingSortType,
|
||||||
|
token: String
|
||||||
|
) = api.getContentRankingBySort(
|
||||||
|
sort = sortType,
|
||||||
|
isAdultContentVisible = SharedPreferenceManager.isAdultContentVisible,
|
||||||
|
contentType = ContentType.entries[SharedPreferenceManager.contentPreference],
|
||||||
|
authHeader = token
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -113,6 +113,9 @@ class HomeViewModel(
|
|||||||
data.pointAvailableContentList
|
data.pointAvailableContentList
|
||||||
_recommendChannelListLiveData.value = data.recommendChannelList
|
_recommendChannelListLiveData.value = data.recommendChannelList
|
||||||
_recommendContentListLiveData.value = data.recommendContentList
|
_recommendContentListLiveData.value = data.recommendContentList
|
||||||
|
|
||||||
|
// 홈 진입 시 기본 정렬(REVENUE) 랭킹을 최신화
|
||||||
|
getContentRanking(ContentRankingSortType.REVENUE)
|
||||||
} else {
|
} else {
|
||||||
if (it.message != null) {
|
if (it.message != null) {
|
||||||
_toastLiveData.postValue(it.message)
|
_toastLiveData.postValue(it.message)
|
||||||
@@ -132,6 +135,32 @@ class HomeViewModel(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getContentRanking(sortType: ContentRankingSortType) {
|
||||||
|
compositeDisposable.add(
|
||||||
|
repository.getContentRanking(sortType, token = "Bearer ${SharedPreferenceManager.token}")
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe(
|
||||||
|
{
|
||||||
|
val data = it.data
|
||||||
|
if (it.success && data != null) {
|
||||||
|
_contentRankingLiveData.value = data
|
||||||
|
} else {
|
||||||
|
if (it.message != null) {
|
||||||
|
_toastLiveData.postValue(it.message)
|
||||||
|
} else {
|
||||||
|
_toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
it.message?.let { message -> Logger.e(message) }
|
||||||
|
_toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
fun refreshRecommendContents() {
|
fun refreshRecommendContents() {
|
||||||
_isLoading.value = true
|
_isLoading.value = true
|
||||||
compositeDisposable.add(
|
compositeDisposable.add(
|
||||||
|
|||||||
@@ -313,8 +313,7 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="48dp"
|
android:layout_marginBottom="48dp"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical">
|
||||||
android:visibility="gone">
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tv_weekly_chart"
|
android:id="@+id/tv_weekly_chart"
|
||||||
@@ -326,6 +325,16 @@
|
|||||||
android:textColor="@color/white"
|
android:textColor="@color/white"
|
||||||
android:textSize="24sp" />
|
android:textSize="24sp" />
|
||||||
|
|
||||||
|
<!-- 정렬 선택 -->
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/rv_weekly_chart_sort"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="12dp"
|
||||||
|
android:clipToPadding="false"
|
||||||
|
android:nestedScrollingEnabled="false"
|
||||||
|
android:paddingHorizontal="24dp" />
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/rv_weekly_chart"
|
android:id="@+id/rv_weekly_chart"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|||||||
Reference in New Issue
Block a user