feat: 메인 라이브
- 라이브 다시 듣기 UI 추가
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
package kr.co.vividnext.sodalive.audio_content
|
package kr.co.vividnext.sodalive.audio_content
|
||||||
|
|
||||||
|
import io.reactivex.rxjava3.core.Flowable
|
||||||
import io.reactivex.rxjava3.core.Single
|
import io.reactivex.rxjava3.core.Single
|
||||||
import kr.co.vividnext.sodalive.audio_content.all.GetNewContentAllResponse
|
import kr.co.vividnext.sodalive.audio_content.all.GetNewContentAllResponse
|
||||||
import kr.co.vividnext.sodalive.audio_content.all.by_theme.GetContentByThemeResponse
|
import kr.co.vividnext.sodalive.audio_content.all.by_theme.GetContentByThemeResponse
|
||||||
@@ -56,6 +57,13 @@ interface AudioContentApi {
|
|||||||
@Header("Authorization") authHeader: String
|
@Header("Authorization") authHeader: String
|
||||||
): Single<ApiResponse<GetAudioContentListResponse>>
|
): Single<ApiResponse<GetAudioContentListResponse>>
|
||||||
|
|
||||||
|
@GET("/audio-content/replay-live")
|
||||||
|
fun getAudioContentReplayLiveList(
|
||||||
|
@Query("isAdultContentVisible") isAdultContentVisible: Boolean,
|
||||||
|
@Query("contentType") contentType: ContentType,
|
||||||
|
@Header("Authorization") authHeader: String
|
||||||
|
): Flowable<ApiResponse<List<GetAudioContentMainItem>>>
|
||||||
|
|
||||||
@GET("/audio-content/theme")
|
@GET("/audio-content/theme")
|
||||||
fun getAudioContentThemeList(
|
fun getAudioContentThemeList(
|
||||||
@Header("Authorization") authHeader: String
|
@Header("Authorization") authHeader: String
|
||||||
|
|||||||
@@ -50,6 +50,12 @@ class AudioContentRepository(
|
|||||||
authHeader = token
|
authHeader = token
|
||||||
)
|
)
|
||||||
|
|
||||||
|
fun getAudioContentReplayLiveList(token: String) = api.getAudioContentReplayLiveList(
|
||||||
|
isAdultContentVisible = SharedPreferenceManager.isAdultContentVisible,
|
||||||
|
contentType = ContentType.values()[SharedPreferenceManager.contentPreference],
|
||||||
|
authHeader = token
|
||||||
|
)
|
||||||
|
|
||||||
fun getAudioContentThemeList(token: String) = api.getAudioContentThemeList(token)
|
fun getAudioContentThemeList(token: String) = api.getAudioContentThemeList(token)
|
||||||
|
|
||||||
fun uploadAudioContent(
|
fun uploadAudioContent(
|
||||||
|
|||||||
@@ -252,7 +252,7 @@ class AppDI(private val context: Context, isDebugMode: Boolean) {
|
|||||||
viewModel { TermsViewModel(get()) }
|
viewModel { TermsViewModel(get()) }
|
||||||
viewModel { FindPasswordViewModel(get()) }
|
viewModel { FindPasswordViewModel(get()) }
|
||||||
viewModel { MainViewModel(get(), get(), get(), get(), get()) }
|
viewModel { MainViewModel(get(), get(), get(), get(), get()) }
|
||||||
viewModel { LiveViewModel(get(), get(), get(), get()) }
|
viewModel { LiveViewModel(get(), get(), get(), get(), get()) }
|
||||||
viewModel { MyPageViewModel(get(), get()) }
|
viewModel { MyPageViewModel(get(), get()) }
|
||||||
viewModel { CanStatusViewModel(get()) }
|
viewModel { CanStatusViewModel(get()) }
|
||||||
viewModel { CanChargePgViewModel(get()) }
|
viewModel { CanChargePgViewModel(get()) }
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import androidx.activity.result.ActivityResultLauncher
|
|||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.media3.common.util.UnstableApi
|
import androidx.media3.common.util.UnstableApi
|
||||||
|
import androidx.recyclerview.widget.GridLayoutManager
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.zhpan.bannerview.BaseBannerAdapter
|
import com.zhpan.bannerview.BaseBannerAdapter
|
||||||
@@ -22,6 +23,7 @@ import com.zhpan.indicator.enums.IndicatorSlideMode
|
|||||||
import com.zhpan.indicator.enums.IndicatorStyle
|
import com.zhpan.indicator.enums.IndicatorStyle
|
||||||
import kr.co.vividnext.sodalive.R
|
import kr.co.vividnext.sodalive.R
|
||||||
import kr.co.vividnext.sodalive.audio_content.AudioContentPlayService
|
import kr.co.vividnext.sodalive.audio_content.AudioContentPlayService
|
||||||
|
import kr.co.vividnext.sodalive.audio_content.detail.AudioContentDetailActivity
|
||||||
import kr.co.vividnext.sodalive.audio_content.player.AudioContentPlayerService
|
import kr.co.vividnext.sodalive.audio_content.player.AudioContentPlayerService
|
||||||
import kr.co.vividnext.sodalive.base.BaseFragment
|
import kr.co.vividnext.sodalive.base.BaseFragment
|
||||||
import kr.co.vividnext.sodalive.common.Constants
|
import kr.co.vividnext.sodalive.common.Constants
|
||||||
@@ -34,6 +36,8 @@ import kr.co.vividnext.sodalive.explorer.profile.creator_community.all.CreatorCo
|
|||||||
import kr.co.vividnext.sodalive.extensions.dpToPx
|
import kr.co.vividnext.sodalive.extensions.dpToPx
|
||||||
import kr.co.vividnext.sodalive.extensions.moneyFormat
|
import kr.co.vividnext.sodalive.extensions.moneyFormat
|
||||||
import kr.co.vividnext.sodalive.following.FollowingCreatorActivity
|
import kr.co.vividnext.sodalive.following.FollowingCreatorActivity
|
||||||
|
import kr.co.vividnext.sodalive.home.AudioContentMainItem
|
||||||
|
import kr.co.vividnext.sodalive.home.HomeContentAdapter
|
||||||
import kr.co.vividnext.sodalive.live.now.LiveNowAdapter
|
import kr.co.vividnext.sodalive.live.now.LiveNowAdapter
|
||||||
import kr.co.vividnext.sodalive.live.now.all.LiveNowAllActivity
|
import kr.co.vividnext.sodalive.live.now.all.LiveNowAllActivity
|
||||||
import kr.co.vividnext.sodalive.live.recommend.RecommendLiveAdapter
|
import kr.co.vividnext.sodalive.live.recommend.RecommendLiveAdapter
|
||||||
@@ -162,6 +166,7 @@ class LiveFragment : BaseFragment<FragmentLiveBinding>(FragmentLiveBinding::infl
|
|||||||
setupRecommendLive()
|
setupRecommendLive()
|
||||||
setupRecommendChannel()
|
setupRecommendChannel()
|
||||||
setupLatestFinishedLiveChannel()
|
setupLatestFinishedLiveChannel()
|
||||||
|
setupLiveReplay()
|
||||||
setupLiveReservation()
|
setupLiveReservation()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -403,6 +408,83 @@ class LiveFragment : BaseFragment<FragmentLiveBinding>(FragmentLiveBinding::infl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun setupLiveReplay() {
|
||||||
|
val adapter = HomeContentAdapter {
|
||||||
|
if (SharedPreferenceManager.token.isNotBlank()) {
|
||||||
|
startActivity(
|
||||||
|
Intent(requireContext(), AudioContentDetailActivity::class.java).apply {
|
||||||
|
putExtra(Constants.EXTRA_AUDIO_CONTENT_ID, it)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
(requireActivity() as MainActivity).showLoginActivity()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val rvContent = binding.rvReplayLive
|
||||||
|
rvContent.layoutManager = GridLayoutManager(context, 2, RecyclerView.HORIZONTAL, false)
|
||||||
|
rvContent.addItemDecoration(object : RecyclerView.ItemDecoration() {
|
||||||
|
override fun getItemOffsets(
|
||||||
|
outRect: Rect,
|
||||||
|
view: View,
|
||||||
|
parent: RecyclerView,
|
||||||
|
state: RecyclerView.State
|
||||||
|
) {
|
||||||
|
super.getItemOffsets(outRect, view, parent, state)
|
||||||
|
outRect.top = 8f.dpToPx().toInt()
|
||||||
|
outRect.bottom = 8f.dpToPx().toInt()
|
||||||
|
|
||||||
|
val position = parent.getChildAdapterPosition(view)
|
||||||
|
|
||||||
|
if (position == 0 || position == 1) {
|
||||||
|
outRect.left = 0f.dpToPx().toInt()
|
||||||
|
} else {
|
||||||
|
outRect.left = 8f.dpToPx().toInt()
|
||||||
|
}
|
||||||
|
|
||||||
|
outRect.right = 8f.dpToPx().toInt()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
rvContent.adapter = adapter
|
||||||
|
|
||||||
|
adapter.registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() {
|
||||||
|
override fun onChanged() {
|
||||||
|
if (adapter.itemCount < 2) {
|
||||||
|
// 1개일 땐 단일 행
|
||||||
|
rvContent.layoutManager =
|
||||||
|
LinearLayoutManager(rvContent.context, RecyclerView.HORIZONTAL, false)
|
||||||
|
} else {
|
||||||
|
// 2개 이상일 땐 2행 바둑판
|
||||||
|
rvContent.layoutManager =
|
||||||
|
GridLayoutManager(rvContent.context, 2, RecyclerView.HORIZONTAL, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
viewModel.replayContentListLiveData.observe(viewLifecycleOwner) { contentList ->
|
||||||
|
if (contentList.isNotEmpty()) {
|
||||||
|
adapter.addItems(
|
||||||
|
contentList.map {
|
||||||
|
AudioContentMainItem(
|
||||||
|
contentId = it.contentId,
|
||||||
|
creatorId = it.creatorId,
|
||||||
|
title = it.title,
|
||||||
|
coverImageUrl = it.coverImageUrl,
|
||||||
|
creatorNickname = it.creatorNickname,
|
||||||
|
isPointAvailable = it.isPointAvailable
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
binding.llReplayLive.visibility = View.VISIBLE
|
||||||
|
binding.rvReplayLive.visibility = View.VISIBLE
|
||||||
|
} else {
|
||||||
|
binding.llReplayLive.visibility = View.GONE
|
||||||
|
binding.rvReplayLive.visibility = View.GONE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressLint("NotifyDataSetChanged")
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
private fun setupLiveNow() {
|
private fun setupLiveNow() {
|
||||||
binding
|
binding
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package kr.co.vividnext.sodalive.live
|
|||||||
|
|
||||||
import androidx.annotation.Keep
|
import androidx.annotation.Keep
|
||||||
import com.google.gson.annotations.SerializedName
|
import com.google.gson.annotations.SerializedName
|
||||||
|
import kr.co.vividnext.sodalive.audio_content.main.GetAudioContentMainItem
|
||||||
import kr.co.vividnext.sodalive.common.ApiResponse
|
import kr.co.vividnext.sodalive.common.ApiResponse
|
||||||
import kr.co.vividnext.sodalive.live.recommend.GetRecommendLiveResponse
|
import kr.co.vividnext.sodalive.live.recommend.GetRecommendLiveResponse
|
||||||
import kr.co.vividnext.sodalive.settings.event.GetEventResponse
|
import kr.co.vividnext.sodalive.settings.event.GetEventResponse
|
||||||
@@ -17,5 +18,7 @@ data class LiveSummary(
|
|||||||
@SerializedName("recommendLive")
|
@SerializedName("recommendLive")
|
||||||
val recommendLive: ApiResponse<List<GetRecommendLiveResponse>>,
|
val recommendLive: ApiResponse<List<GetRecommendLiveResponse>>,
|
||||||
@SerializedName("latestFinishedLive")
|
@SerializedName("latestFinishedLive")
|
||||||
val latestFinishedLive: ApiResponse<List<GetLatestFinishedLiveResponse>>
|
val latestFinishedLive: ApiResponse<List<GetLatestFinishedLiveResponse>>,
|
||||||
|
@SerializedName("replayLive")
|
||||||
|
val replayLive: ApiResponse<List<GetAudioContentMainItem>>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -6,10 +6,13 @@ import com.orhanobut.logger.Logger
|
|||||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
||||||
import io.reactivex.rxjava3.core.Flowable
|
import io.reactivex.rxjava3.core.Flowable
|
||||||
import io.reactivex.rxjava3.schedulers.Schedulers
|
import io.reactivex.rxjava3.schedulers.Schedulers
|
||||||
|
import kr.co.vividnext.sodalive.audio_content.AudioContentRepository
|
||||||
|
import kr.co.vividnext.sodalive.audio_content.main.GetAudioContentMainItem
|
||||||
import kr.co.vividnext.sodalive.base.BaseViewModel
|
import kr.co.vividnext.sodalive.base.BaseViewModel
|
||||||
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
||||||
import kr.co.vividnext.sodalive.explorer.profile.creator_community.CreatorCommunityRepository
|
import kr.co.vividnext.sodalive.explorer.profile.creator_community.CreatorCommunityRepository
|
||||||
import kr.co.vividnext.sodalive.explorer.profile.creator_community.GetCommunityPostListResponse
|
import kr.co.vividnext.sodalive.explorer.profile.creator_community.GetCommunityPostListResponse
|
||||||
|
import kr.co.vividnext.sodalive.home.AudioContentMainItem
|
||||||
import kr.co.vividnext.sodalive.live.recommend.GetRecommendLiveResponse
|
import kr.co.vividnext.sodalive.live.recommend.GetRecommendLiveResponse
|
||||||
import kr.co.vividnext.sodalive.live.recommend.LiveRecommendRepository
|
import kr.co.vividnext.sodalive.live.recommend.LiveRecommendRepository
|
||||||
import kr.co.vividnext.sodalive.live.recommend_channel.GetRecommendChannelResponse
|
import kr.co.vividnext.sodalive.live.recommend_channel.GetRecommendChannelResponse
|
||||||
@@ -26,6 +29,7 @@ import kr.co.vividnext.sodalive.settings.event.EventRepository
|
|||||||
class LiveViewModel(
|
class LiveViewModel(
|
||||||
private val repository: LiveRepository,
|
private val repository: LiveRepository,
|
||||||
private val eventRepository: EventRepository,
|
private val eventRepository: EventRepository,
|
||||||
|
private val contentRepository: AudioContentRepository,
|
||||||
private val liveRecommendRepository: LiveRecommendRepository,
|
private val liveRecommendRepository: LiveRecommendRepository,
|
||||||
private val creatorCommunityRepository: CreatorCommunityRepository
|
private val creatorCommunityRepository: CreatorCommunityRepository
|
||||||
) : BaseViewModel() {
|
) : BaseViewModel() {
|
||||||
@@ -61,6 +65,10 @@ class LiveViewModel(
|
|||||||
val communityPostItemLiveData: LiveData<List<GetCommunityPostListResponse>>
|
val communityPostItemLiveData: LiveData<List<GetCommunityPostListResponse>>
|
||||||
get() = _communityPostItemLiveData
|
get() = _communityPostItemLiveData
|
||||||
|
|
||||||
|
private var _replayContentListLiveData = MutableLiveData<List<GetAudioContentMainItem>>()
|
||||||
|
val replayContentListLiveData: LiveData<List<GetAudioContentMainItem>>
|
||||||
|
get() = _replayContentListLiveData
|
||||||
|
|
||||||
private val _latestFinishedLiveListLiveData =
|
private val _latestFinishedLiveListLiveData =
|
||||||
MutableLiveData<List<GetLatestFinishedLiveResponse>>()
|
MutableLiveData<List<GetLatestFinishedLiveResponse>>()
|
||||||
val latestFinishedLiveListLiveData: LiveData<List<GetLatestFinishedLiveResponse>>
|
val latestFinishedLiveListLiveData: LiveData<List<GetLatestFinishedLiveResponse>>
|
||||||
@@ -166,6 +174,10 @@ class LiveViewModel(
|
|||||||
token = "Bearer ${SharedPreferenceManager.token}"
|
token = "Bearer ${SharedPreferenceManager.token}"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
val replayLive = contentRepository.getAudioContentReplayLiveList(
|
||||||
|
token = "Bearer ${SharedPreferenceManager.token}"
|
||||||
|
)
|
||||||
|
|
||||||
_isLoading.postValue(true)
|
_isLoading.postValue(true)
|
||||||
|
|
||||||
compositeDisposable.add(
|
compositeDisposable.add(
|
||||||
@@ -174,8 +186,18 @@ class LiveViewModel(
|
|||||||
liveReservation,
|
liveReservation,
|
||||||
event,
|
event,
|
||||||
recommendLive,
|
recommendLive,
|
||||||
latestFinishedLive
|
latestFinishedLive,
|
||||||
) { t1, t2, t3, t4, t5 -> LiveSummary(t1, t2, t3, t4, t5) }
|
replayLive
|
||||||
|
) { t1, t2, t3, t4, t5, t6 ->
|
||||||
|
LiveSummary(
|
||||||
|
liveNow = t1,
|
||||||
|
liveReservation = t2,
|
||||||
|
event = t3,
|
||||||
|
recommendLive = t4,
|
||||||
|
latestFinishedLive = t5,
|
||||||
|
replayLive = t6
|
||||||
|
)
|
||||||
|
}
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.subscribe(
|
.subscribe(
|
||||||
{
|
{
|
||||||
@@ -245,6 +267,12 @@ class LiveViewModel(
|
|||||||
_latestFinishedLiveListLiveData.postValue(emptyList())
|
_latestFinishedLiveListLiveData.postValue(emptyList())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val replayLive = it.replayLive
|
||||||
|
if (replayLive.success && replayLive.data != null) {
|
||||||
|
val data = replayLive.data!!
|
||||||
|
_replayContentListLiveData.postValue(data)
|
||||||
|
}
|
||||||
|
|
||||||
_isLoading.postValue(false)
|
_isLoading.postValue(false)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -134,6 +134,38 @@
|
|||||||
android:clipToPadding="false"
|
android:clipToPadding="false"
|
||||||
android:paddingHorizontal="24dp" />
|
android:paddingHorizontal="24dp" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/ll_replay_live"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginHorizontal="24dp"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:fontFamily="@font/pretendard_bold"
|
||||||
|
android:text="라이브 "
|
||||||
|
android:textColor="@color/color_3bb9f1"
|
||||||
|
android:textSize="26sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:fontFamily="@font/pretendard_bold"
|
||||||
|
android:text="다시 듣기"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textSize="26sp" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/rv_replay_live"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:layout_marginBottom="48dp"
|
||||||
|
android:clipToPadding="false"
|
||||||
|
android:paddingHorizontal="24dp" />
|
||||||
|
|
||||||
<include
|
<include
|
||||||
android:id="@+id/layout_recommend_channel"
|
android:id="@+id/layout_recommend_channel"
|
||||||
|
|||||||
Reference in New Issue
Block a user