From e5acc5468fa918287afc5a690bb7f482957963ca Mon Sep 17 00:00:00 2001 From: klaus Date: Sat, 15 Feb 2025 03:03:42 +0900 Subject: [PATCH] =?UTF-8?q?=EC=BD=98=ED=85=90=EC=B8=A0=20=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=EB=8B=A4=EC=8B=9C=EB=93=A3=EA=B8=B0=20=ED=83=AD=20?= =?UTF-8?q?-=20=EC=B1=84=EB=84=90=EB=B3=84=20=EB=9D=BC=EC=9D=B4=EB=B8=8C?= =?UTF-8?q?=20=EB=8B=A4=EC=8B=9C=EB=93=A3=EA=B8=B0=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sodalive/audio_content/AudioContentApi.kt | 6 + .../main/v2/asmr/AsmrNewContentAllActivity.kt | 2 + .../AudioContentMainTabReplayFragment.kt | 158 +++++++++ .../AudioContentMainTabReplayRepository.kt | 4 + .../AudioContentMainTabReplayViewModel.kt | 54 +++ .../GetContentMainTabLiveReplayResponse.kt | 22 +- ...fragment_audio_content_main_tab_replay.xml | 317 ++++++++++++++++++ 7 files changed, 558 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/kr/co/vividnext/sodalive/audio_content/AudioContentApi.kt b/app/src/main/java/kr/co/vividnext/sodalive/audio_content/AudioContentApi.kt index b3f702f..bf7dff6 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/audio_content/AudioContentApi.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/audio_content/AudioContentApi.kt @@ -344,6 +344,12 @@ interface AudioContentApi { @Header("Authorization") authHeader: String ): Single> + @GET("/v2/audio-content/main/replay/popular-content-by-creator") + fun getPopularReplayContentByCreator( + @Query("creatorId") creatorId: Long, + @Header("Authorization") authHeader: String + ): Single> + @GET("/v2/audio-content/main/free") fun getContentMainFree( @Header("Authorization") authHeader: String diff --git a/app/src/main/java/kr/co/vividnext/sodalive/audio_content/main/v2/asmr/AsmrNewContentAllActivity.kt b/app/src/main/java/kr/co/vividnext/sodalive/audio_content/main/v2/asmr/AsmrNewContentAllActivity.kt index 4b2302c..4829154 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/audio_content/main/v2/asmr/AsmrNewContentAllActivity.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/audio_content/main/v2/asmr/AsmrNewContentAllActivity.kt @@ -1,5 +1,6 @@ package kr.co.vividnext.sodalive.audio_content.main.v2.asmr +import android.annotation.SuppressLint import android.content.Intent import android.os.Bundle import android.widget.Toast @@ -36,6 +37,7 @@ class AsmrNewContentAllActivity : BaseActivity viewModel.selectTheme(theme = "ASMR", isFree = false) } + @SuppressLint("SetTextI18n") override fun setupView() { loadingDialog = LoadingDialog(this, layoutInflater) binding.toolbar.tvBack.text = "새로운 ASMR" diff --git a/app/src/main/java/kr/co/vividnext/sodalive/audio_content/main/v2/replay/AudioContentMainTabReplayFragment.kt b/app/src/main/java/kr/co/vividnext/sodalive/audio_content/main/v2/replay/AudioContentMainTabReplayFragment.kt index 4287134..117eb42 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/audio_content/main/v2/replay/AudioContentMainTabReplayFragment.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/audio_content/main/v2/replay/AudioContentMainTabReplayFragment.kt @@ -6,7 +6,9 @@ import android.graphics.Rect import android.net.Uri import android.os.Bundle import android.view.View +import android.widget.ImageView import android.widget.LinearLayout +import android.widget.TextView import android.widget.Toast import androidx.annotation.OptIn import androidx.core.content.ContextCompat @@ -14,6 +16,9 @@ import androidx.media3.common.util.UnstableApi import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView +import coil.load +import coil.transform.CircleCropTransformation +import coil.transform.RoundedCornersTransformation import com.zhpan.bannerview.BaseBannerAdapter import com.zhpan.indicator.enums.IndicatorSlideMode import com.zhpan.indicator.enums.IndicatorStyle @@ -21,9 +26,11 @@ import kr.co.vividnext.sodalive.R import kr.co.vividnext.sodalive.audio_content.detail.AudioContentDetailActivity import kr.co.vividnext.sodalive.audio_content.main.AudioContentBannerType import kr.co.vividnext.sodalive.audio_content.main.AudioContentMainContentAdapter +import kr.co.vividnext.sodalive.audio_content.main.GetAudioContentRankingItem import kr.co.vividnext.sodalive.audio_content.main.banner.AudioContentMainBannerAdapter import kr.co.vividnext.sodalive.audio_content.main.ranking.AudioContentMainRankingAdapter import kr.co.vividnext.sodalive.audio_content.main.v2.AudioContentMainContentCurationAdapter +import kr.co.vividnext.sodalive.audio_content.main.v2.ContentRankCreatorAdapter import kr.co.vividnext.sodalive.audio_content.series.detail.SeriesDetailActivity import kr.co.vividnext.sodalive.base.BaseFragment import kr.co.vividnext.sodalive.common.Constants @@ -47,6 +54,7 @@ class AudioContentMainTabReplayFragment : BaseFragment { + outRect.left = 0 + outRect.right = 4f.dpToPx().toInt() + } + + contentRankCreatorAdapter.itemCount - 1 -> { + outRect.left = 4f.dpToPx().toInt() + outRect.right = 0 + } + + else -> { + outRect.left = 4f.dpToPx().toInt() + outRect.right = 4f.dpToPx().toInt() + } + } + } + }) + + binding.rvRankingCreator.adapter = contentRankCreatorAdapter + + viewModel.contentCreatorListLiveData.observe(viewLifecycleOwner) { + contentRankCreatorAdapter.addItems(it) + if (contentRankCreatorAdapter.itemCount <= 0 && it.isEmpty()) { + binding.llCreatorContentRanking.visibility = View.GONE + } else { + binding.llCreatorContentRanking.visibility = View.VISIBLE + } + } + } + + private fun loadingPopularContentByCreator() { + binding.llSales2.visibility = View.GONE + binding.llSalesTop2.visibility = View.GONE + binding.llSalesCount2.visibility = View.GONE + binding.llSalesCountTop2.visibility = View.GONE + binding.llNoItems.visibility = View.VISIBLE + } + private fun setupEventBanner() { val imageSliderLp = binding.eventBannerSlider.layoutParams imageSliderLp.width = screenWidth @@ -391,5 +460,94 @@ class AudioContentMainTabReplayFragment : BaseFragment 1) { + binding.llSales2.visibility = View.VISIBLE + setSalesRankContent( + item = it[1], + titleTextView = binding.tvSalesTitle2, + coverImageView = binding.ivSales2, + creatorTextView = binding.tvSalesCreator2, + creatorImageView = binding.ivSalesCreator2 + ) + } + } + } + + viewModel.salesCountRankContentListLiveData.observe(viewLifecycleOwner) { + if (it.isNotEmpty()) { + binding.llNoItems.visibility = View.GONE + binding.llSalesCountTop2.visibility = View.VISIBLE + + setSalesRankContent( + item = it[0], + titleTextView = binding.tvSalesCountTitle1, + coverImageView = binding.ivSalesCount1, + creatorTextView = binding.tvSalesCountCreator1, + creatorImageView = binding.ivSalesCountCreator1 + ) + + if (it.size > 1) { + binding.llSalesCount2.visibility = View.VISIBLE + setSalesRankContent( + item = it[1], + titleTextView = binding.tvSalesCountTitle2, + coverImageView = binding.ivSalesCount2, + creatorTextView = binding.tvSalesCountCreator2, + creatorImageView = binding.ivSalesCountCreator2 + ) + } + } + } + } + + private fun setSalesRankContent( + item: GetAudioContentRankingItem, + titleTextView: TextView, + creatorTextView: TextView, + coverImageView: ImageView, + creatorImageView: ImageView + ) { + coverImageView.load(item.coverImageUrl) { + crossfade(true) + placeholder(R.drawable.bg_placeholder) + transformations(RoundedCornersTransformation(5.3f.dpToPx())) + } + titleTextView.text = item.title + creatorTextView.text = item.creatorNickname + creatorImageView.load(item.creatorProfileImageUrl) { + transformations(CircleCropTransformation()) + placeholder(R.drawable.ic_place_holder) + crossfade(true) + } + + coverImageView.setOnClickListener { + startActivity( + Intent(requireActivity(), AudioContentDetailActivity::class.java).apply { + putExtra(Constants.EXTRA_AUDIO_CONTENT_ID, item.contentId) + } + ) + } + + creatorImageView.setOnClickListener { + startActivity( + Intent(requireActivity(), UserProfileActivity::class.java).apply { + putExtra(Constants.EXTRA_USER_ID, item.creatorId) + } + ) + } } } diff --git a/app/src/main/java/kr/co/vividnext/sodalive/audio_content/main/v2/replay/AudioContentMainTabReplayRepository.kt b/app/src/main/java/kr/co/vividnext/sodalive/audio_content/main/v2/replay/AudioContentMainTabReplayRepository.kt index ff1509c..0272490 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/audio_content/main/v2/replay/AudioContentMainTabReplayRepository.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/audio_content/main/v2/replay/AudioContentMainTabReplayRepository.kt @@ -4,4 +4,8 @@ import kr.co.vividnext.sodalive.audio_content.AudioContentApi class AudioContentMainTabReplayRepository(private val api: AudioContentApi) { fun getContentMainReplay(token: String) = api.getContentMainReplay(authHeader = token) + fun getPopularContentByCreator( + creatorId: Long, + token: String + ) = api.getPopularReplayContentByCreator(creatorId, authHeader = token) } diff --git a/app/src/main/java/kr/co/vividnext/sodalive/audio_content/main/v2/replay/AudioContentMainTabReplayViewModel.kt b/app/src/main/java/kr/co/vividnext/sodalive/audio_content/main/v2/replay/AudioContentMainTabReplayViewModel.kt index dfb8686..9567cca 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/audio_content/main/v2/replay/AudioContentMainTabReplayViewModel.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/audio_content/main/v2/replay/AudioContentMainTabReplayViewModel.kt @@ -5,6 +5,7 @@ import androidx.lifecycle.MutableLiveData import com.orhanobut.logger.Logger import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers import io.reactivex.rxjava3.schedulers.Schedulers +import kr.co.vividnext.sodalive.audio_content.main.ContentCreatorResponse import kr.co.vividnext.sodalive.audio_content.main.GetAudioContentBannerResponse import kr.co.vividnext.sodalive.audio_content.main.GetAudioContentMainItem import kr.co.vividnext.sodalive.audio_content.main.GetAudioContentRankingItem @@ -36,6 +37,19 @@ class AudioContentMainTabReplayViewModel( val contentRankingLiveData: LiveData> get() = _contentRankingLiveData + private val _contentCreatorListLiveData = MutableLiveData>() + val contentCreatorListLiveData: LiveData> + get() = _contentCreatorListLiveData + + private val _salesRankContentListLiveData = MutableLiveData>() + val salesRankContentListLiveData: LiveData> + get() = _salesRankContentListLiveData + + private val _salesCountRankContentListLiveData = + MutableLiveData>() + val salesCountRankContentListLiveData: LiveData> + get() = _salesCountRankContentListLiveData + private val _eventLiveData = MutableLiveData>() val eventLiveData: LiveData> get() = _eventLiveData @@ -59,6 +73,10 @@ class AudioContentMainTabReplayViewModel( _contentBannerLiveData.value = data.contentBannerList _newContentListLiveData.value = data.newLiveReplayContentList _contentRankingLiveData.value = data.rankLiveReplayContentList + _contentCreatorListLiveData.value = data.creatorList + _salesRankContentListLiveData.value = data.salesRankContentList + _salesCountRankContentListLiveData.value = + data.salesCountRankContentList _eventLiveData.value = data.eventBannerList.eventList _curationListLiveData.value = data.curationList } else { @@ -81,4 +99,40 @@ class AudioContentMainTabReplayViewModel( ) ) } + + fun getPopularContentByCreator(creatorId: Long) { + _isLoading.value = true + compositeDisposable.add( + repository.getPopularContentByCreator( + creatorId = creatorId, + token = "Bearer ${SharedPreferenceManager.token}" + ) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe( + { + _isLoading.value = false + if (it.success && it.data != null) { + val data = it.data + _salesRankContentListLiveData.value = data.salesRankContentList + _salesCountRankContentListLiveData.value = + data.salesCountRankContentList + } else { + if (it.message != null) { + _toastLiveData.postValue(it.message) + } else { + _toastLiveData.postValue( + "알 수 없는 오류가 발생했습니다. 다시 시도해 주세요." + ) + } + } + }, + { + _isLoading.value = false + it.message?.let { message -> Logger.e(message) } + _toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.") + } + ) + ) + } } diff --git a/app/src/main/java/kr/co/vividnext/sodalive/audio_content/main/v2/replay/GetContentMainTabLiveReplayResponse.kt b/app/src/main/java/kr/co/vividnext/sodalive/audio_content/main/v2/replay/GetContentMainTabLiveReplayResponse.kt index c23f534..e1ee501 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/audio_content/main/v2/replay/GetContentMainTabLiveReplayResponse.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/audio_content/main/v2/replay/GetContentMainTabLiveReplayResponse.kt @@ -2,6 +2,7 @@ package kr.co.vividnext.sodalive.audio_content.main.v2.replay import androidx.annotation.Keep import com.google.gson.annotations.SerializedName +import kr.co.vividnext.sodalive.audio_content.main.ContentCreatorResponse import kr.co.vividnext.sodalive.audio_content.main.GetAudioContentBannerResponse import kr.co.vividnext.sodalive.audio_content.main.GetAudioContentMainItem import kr.co.vividnext.sodalive.audio_content.main.GetAudioContentRankingItem @@ -10,9 +11,20 @@ import kr.co.vividnext.sodalive.settings.event.GetEventResponse @Keep data class GetContentMainTabLiveReplayResponse( - @SerializedName("contentBannerList") val contentBannerList: List, - @SerializedName("newLiveReplayContentList") val newLiveReplayContentList: List, - @SerializedName("rankLiveReplayContentList") val rankLiveReplayContentList: List, - @SerializedName("eventBannerList") val eventBannerList: GetEventResponse, - @SerializedName("curationList") val curationList: List + @SerializedName("contentBannerList") + val contentBannerList: List, + @SerializedName("newLiveReplayContentList") + val newLiveReplayContentList: List, + @SerializedName("rankLiveReplayContentList") + val rankLiveReplayContentList: List, + @SerializedName("creatorList") + val creatorList: List, + @SerializedName("salesRankContentList") + val salesRankContentList: List, + @SerializedName("salesCountRankContentList") + val salesCountRankContentList: List, + @SerializedName("eventBannerList") + val eventBannerList: GetEventResponse, + @SerializedName("curationList") + val curationList: List ) diff --git a/app/src/main/res/layout/fragment_audio_content_main_tab_replay.xml b/app/src/main/res/layout/fragment_audio_content_main_tab_replay.xml index e96df64..5321e72 100644 --- a/app/src/main/res/layout/fragment_audio_content_main_tab_replay.xml +++ b/app/src/main/res/layout/fragment_audio_content_main_tab_replay.xml @@ -1,5 +1,7 @@ @@ -88,6 +90,321 @@ android:paddingHorizontal="6.7dp" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +