feat: 메인 라이브

- 새로운 UI의 기본 골격 적용
This commit is contained in:
2025-07-16 22:07:07 +09:00
parent 386f9aae32
commit 0c7c7946c6
11 changed files with 219 additions and 391 deletions

View File

@@ -5,7 +5,6 @@ import android.app.Activity
import android.content.Intent
import android.content.SharedPreferences
import android.graphics.Rect
import android.net.Uri
import android.os.Bundle
import android.os.Handler
import android.os.Looper
@@ -23,7 +22,6 @@ import com.zhpan.indicator.enums.IndicatorSlideMode
import com.zhpan.indicator.enums.IndicatorStyle
import kr.co.vividnext.sodalive.R
import kr.co.vividnext.sodalive.audio_content.AudioContentPlayService
import kr.co.vividnext.sodalive.audio_content.all.by_theme.AudioContentAllByThemeActivity
import kr.co.vividnext.sodalive.audio_content.player.AudioContentPlayerService
import kr.co.vividnext.sodalive.base.BaseFragment
import kr.co.vividnext.sodalive.common.Constants
@@ -36,7 +34,6 @@ import kr.co.vividnext.sodalive.explorer.profile.creator_community.all.CreatorCo
import kr.co.vividnext.sodalive.extensions.dpToPx
import kr.co.vividnext.sodalive.extensions.moneyFormat
import kr.co.vividnext.sodalive.following.FollowingCreatorActivity
import kr.co.vividnext.sodalive.live.event_banner.EventBannerAdapter
import kr.co.vividnext.sodalive.live.now.LiveNowAdapter
import kr.co.vividnext.sodalive.live.now.all.LiveNowAllActivity
import kr.co.vividnext.sodalive.live.recommend.RecommendLiveAdapter
@@ -54,7 +51,8 @@ import kr.co.vividnext.sodalive.live.room.dialog.LiveRoomPasswordDialog
import kr.co.vividnext.sodalive.live.room.update.LiveRoomEditActivity
import kr.co.vividnext.sodalive.main.MainActivity
import kr.co.vividnext.sodalive.message.MessageActivity
import kr.co.vividnext.sodalive.settings.event.EventDetailActivity
import kr.co.vividnext.sodalive.mypage.can.charge.CanChargeActivity
import kr.co.vividnext.sodalive.search.SearchActivity
import kr.co.vividnext.sodalive.settings.notification.MemberRole
import org.koin.android.ext.android.inject
import java.text.SimpleDateFormat
@@ -121,24 +119,6 @@ class LiveFragment : BaseFragment<FragmentLiveBinding>(FragmentLiveBinding::infl
SharedPreferenceManager.registerOnSharedPreferenceChangeListener(preferenceChangeListener)
setupView()
setupRecommendLive()
setupRecommendChannel()
setupLiveNow()
setupLiveReservation()
setupEvent()
setupCommunityPost()
binding.llReviewLive.setOnClickListener {
if (SharedPreferenceManager.token.isNotBlank()) {
startActivity(
Intent(requireContext(), AudioContentAllByThemeActivity::class.java).apply {
putExtra(Constants.EXTRA_THEME_ID, 7L)
}
)
} else {
(requireActivity() as MainActivity).showLoginActivity()
}
}
message = "라이브를 불러오고 있습니다."
viewModel.getSummary()
@@ -175,6 +155,48 @@ class LiveFragment : BaseFragment<FragmentLiveBinding>(FragmentLiveBinding::infl
val intent = Intent(requireContext(), LiveRoomCreateActivity::class.java)
activityResultLauncher.launch(intent)
}
setupToolbar()
setupLiveNow()
setupCommunityPost()
setupRecommendLive()
setupRecommendChannel()
setupLiveReservation()
}
private fun setupToolbar() {
if (SharedPreferenceManager.token.isNotBlank()) {
binding.llShortIcon.visibility = View.VISIBLE
binding.ivSearch.setOnClickListener {
startActivity(
Intent(
requireContext(),
SearchActivity::class.java
)
)
}
binding.ivCharge.setOnClickListener {
startActivity(
Intent(
requireContext(),
CanChargeActivity::class.java
)
)
}
binding.ivMessage.setOnClickListener {
startActivity(
Intent(
requireContext(),
MessageActivity::class.java
)
)
}
} else {
binding.llShortIcon.visibility = View.GONE
}
}
private fun refreshSummary() {
@@ -188,22 +210,6 @@ class LiveFragment : BaseFragment<FragmentLiveBinding>(FragmentLiveBinding::infl
@SuppressLint("NotifyDataSetChanged")
private fun setupRecommendLive() {
binding.layoutRecommendLive.ivMessage.visibility = if (
SharedPreferenceManager.token.isNotBlank()
) {
View.VISIBLE
} else {
View.GONE
}
binding.layoutRecommendLive.ivMessage.setOnClickListener {
if (SharedPreferenceManager.token.isNotBlank()) {
startActivity(Intent(requireContext(), MessageActivity::class.java))
} else {
(requireActivity() as MainActivity).showLoginActivity()
}
}
val layoutParams = binding
.layoutRecommendLive
.pager
@@ -255,6 +261,12 @@ class LiveFragment : BaseFragment<FragmentLiveBinding>(FragmentLiveBinding::infl
if (it.isNotEmpty()) {
binding.layoutRecommendLive.root.visibility = View.VISIBLE
binding.layoutRecommendLive.pager.refreshData(it)
if (it.size > 1) {
binding.layoutRecommendLive.indicator2.visibility = View.VISIBLE
} else {
binding.layoutRecommendLive.indicator2.visibility = View.GONE
}
} else {
binding.layoutRecommendLive.root.visibility = View.GONE
}
@@ -304,17 +316,17 @@ class LiveFragment : BaseFragment<FragmentLiveBinding>(FragmentLiveBinding::infl
when (parent.getChildAdapterPosition(view)) {
0 -> {
outRect.left = 0.dpToPx().toInt()
outRect.right = 8.3f.dpToPx().toInt()
outRect.right = 8f.dpToPx().toInt()
}
liveRecommendChannelAdapter.itemCount - 1 -> {
outRect.left = 8.3f.dpToPx().toInt()
outRect.left = 8f.dpToPx().toInt()
outRect.right = 0.dpToPx().toInt()
}
else -> {
outRect.left = 8.3f.dpToPx().toInt()
outRect.right = 8.3f.dpToPx().toInt()
outRect.left = 8f.dpToPx().toInt()
outRect.right = 8f.dpToPx().toInt()
}
}
}
@@ -323,36 +335,16 @@ class LiveFragment : BaseFragment<FragmentLiveBinding>(FragmentLiveBinding::infl
binding.layoutRecommendChannel.rvRecommendChannel.adapter = liveRecommendChannelAdapter
if (SharedPreferenceManager.token.isNotBlank()) {
binding.layoutRecommendChannel.tvFollowingChannel.visibility = View.VISIBLE
binding.layoutRecommendChannel.ivSwitch.visibility = View.VISIBLE
binding.layoutRecommendChannel.ivSwitch.setOnClickListener {
viewModel.toggleIsFollowedCreatorLive()
viewModel.recommendChannelLiveData.observe(viewLifecycleOwner) {
if (it.isNotEmpty()) {
binding.layoutRecommendChannel.root.visibility = View.VISIBLE
liveRecommendChannelAdapter.addItems(it)
} else {
binding.layoutRecommendChannel.root.visibility = View.GONE
}
}
} else {
binding.layoutRecommendChannel.tvFollowingChannel.visibility = View.GONE
binding.layoutRecommendChannel.ivSwitch.visibility = View.GONE
}
viewModel.recommendChannelLiveData.observe(viewLifecycleOwner) {
binding.layoutRecommendChannel.root.visibility = View.VISIBLE
liveRecommendChannelAdapter.addItems(it)
binding.layoutRecommendChannel.rvRecommendChannel.requestLayout()
binding.layoutRecommendChannel.root.requestLayout()
}
viewModel.isFollowedCreatorLive.observe(viewLifecycleOwner) {
liveRecommendChannelAdapter.isFollowedCreatorLive = it
liveRecommendChannelAdapter.clear()
if (it) {
binding.layoutRecommendChannel.ivSwitch.setImageResource(R.drawable.btn_toggle_on_big)
binding.layoutRecommendChannel.llTitle2.visibility = View.VISIBLE
binding.layoutRecommendChannel.llTitle1.visibility = View.GONE
} else {
binding.layoutRecommendChannel.ivSwitch.setImageResource(R.drawable.btn_toggle_off_big)
binding.layoutRecommendChannel.llTitle1.visibility = View.VISIBLE
binding.layoutRecommendChannel.llTitle2.visibility = View.GONE
}
binding.layoutRecommendChannel.root.visibility = View.GONE
}
}
@@ -376,7 +368,7 @@ class LiveFragment : BaseFragment<FragmentLiveBinding>(FragmentLiveBinding::infl
val recyclerView = binding
.layoutLiveNow
.rvSudaNow
.rvLiveNow
liveNowAdapter = LiveNowAdapter {
if (SharedPreferenceManager.token.isNotBlank()) {
@@ -459,7 +451,7 @@ class LiveFragment : BaseFragment<FragmentLiveBinding>(FragmentLiveBinding::infl
private fun setupLiveReservation() {
val recyclerView = binding
.layoutLiveReservation
.rvSudaReservation
.rvLiveReservation
liveReservationAdapter = LiveReservationAdapter(isMain = true) {
if (SharedPreferenceManager.token.isNotBlank()) {
@@ -555,58 +547,6 @@ class LiveFragment : BaseFragment<FragmentLiveBinding>(FragmentLiveBinding::infl
}
}
@SuppressLint("NotifyDataSetChanged")
private fun setupEvent() {
val imageSliderLp = binding.eventBannerSlider.layoutParams
imageSliderLp.width = screenWidth
imageSliderLp.height = (screenWidth * 300) / 1000
binding.eventBannerSlider.layoutParams = imageSliderLp
binding.eventBannerSlider.apply {
adapter = EventBannerAdapter(requireContext()) {
if (SharedPreferenceManager.token.isNotBlank()) {
if (it.detailImageUrl != null) {
val intent = Intent(requireActivity(), EventDetailActivity::class.java)
intent.putExtra(Constants.EXTRA_EVENT, it)
startActivity(intent)
} else if (!it.link.isNullOrBlank()) {
startActivity(
Intent(
Intent.ACTION_VIEW,
Uri.parse(it.link)
)
)
}
} else {
(requireActivity() as MainActivity).showLoginActivity()
}
} as BaseBannerAdapter<Any>
setLifecycleRegistry(lifecycle)
setScrollDuration(800)
}.create()
binding.eventBannerSlider
.setIndicatorView(binding.indicator)
.setIndicatorStyle(IndicatorStyle.ROUND_RECT)
.setIndicatorSlideMode(IndicatorSlideMode.SMOOTH)
.setIndicatorVisibility(View.GONE)
.setIndicatorSliderColor(
ContextCompat.getColor(requireContext(), R.color.color_909090),
ContextCompat.getColor(requireContext(), R.color.color_3bb9f1)
)
.setIndicatorSliderWidth(4f.dpToPx().toInt(), 10f.dpToPx().toInt())
.setIndicatorHeight(4f.dpToPx().toInt())
viewModel.eventLiveData.observe(viewLifecycleOwner) {
if (it.isNotEmpty()) {
binding.eventBannerSlider.visibility = View.VISIBLE
binding.eventBannerSlider.refreshData(it)
} else {
binding.eventBannerSlider.visibility = View.GONE
}
}
}
@SuppressLint("NotifyDataSetChanged")
private fun setupCommunityPost() {
val recyclerView = binding.rvCommunityPost
@@ -664,11 +604,13 @@ class LiveFragment : BaseFragment<FragmentLiveBinding>(FragmentLiveBinding::infl
viewModel.communityPostItemLiveData.observe(viewLifecycleOwner) {
if (it.isNotEmpty()) {
recyclerView.visibility = View.VISIBLE
binding.tvCommunityPost.visibility = View.VISIBLE
creatorCommunityAdapter.items.clear()
creatorCommunityAdapter.items.addAll(it)
creatorCommunityAdapter.notifyDataSetChanged()
} else {
recyclerView.visibility = View.GONE
binding.tvCommunityPost.visibility = View.GONE
}
}
}

View File

@@ -41,12 +41,6 @@ class LiveViewModel(
val recommendLiveData: LiveData<List<GetRecommendLiveResponse>>
get() = _recommendLiveData
private val _isFollowedCreatorLive = MutableLiveData(
SharedPreferenceManager.isFollowedCreatorLive
)
val isFollowedCreatorLive: LiveData<Boolean>
get() = _isFollowedCreatorLive
private val _recommendChannelLiveData = MutableLiveData<List<GetRecommendChannelResponse>>()
val recommendChannelLiveData: LiveData<List<GetRecommendChannelResponse>>
get() = _recommendChannelLiveData
@@ -71,17 +65,6 @@ class LiveViewModel(
var isLast = false
private val pageSize = 10
fun toggleIsFollowedCreatorLive() {
val isOn = !_isFollowedCreatorLive.value!!
SharedPreferenceManager.isFollowedCreatorLive = isOn
_isFollowedCreatorLive.value = isOn
if (_isFollowedCreatorLive.value!!) {
getFollowedChannelList()
} else {
getRecommendChannelList()
}
}
private fun getFollowedChannelList() {
compositeDisposable.add(
liveRecommendRepository.getFollowingChannelList(
@@ -112,36 +95,6 @@ class LiveViewModel(
)
}
private fun getRecommendChannelList() {
compositeDisposable.add(
liveRecommendRepository.getRecommendChannelList(
token = "Bearer ${SharedPreferenceManager.token}"
)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
{
if (it.success && it.data != null) {
_recommendChannelLiveData.postValue(it.data!!)
} else {
if (it.message != null) {
_toastLiveData.postValue(it.message)
} else {
_toastLiveData.postValue(
"알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
)
}
}
},
{
_isLoading.value = false
it.message?.let { message -> Logger.e(message) }
_toastLiveData.postValue("알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.")
}
)
)
}
private fun getLatestPostListFromCreatorsYouFollow() {
compositeDisposable.add(
creatorCommunityRepository.getLatestPostListFromCreatorsYouFollow(
@@ -174,13 +127,9 @@ class LiveViewModel(
fun getSummary() {
if (!_isLoading.value!!) {
if (_isFollowedCreatorLive.value!!) {
getFollowedChannelList()
} else {
getRecommendChannelList()
}
if (SharedPreferenceManager.token.isNotBlank()) {
getFollowedChannelList()
getLatestPostListFromCreatorsYouFollow()
}

View File

@@ -17,8 +17,6 @@ class LiveRecommendChannelAdapter(
private val onClickMore: () -> Unit,
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
var isFollowedCreatorLive = false
private val items = mutableListOf<GetRecommendChannelResponse>()
class FooterViewHolder(
@@ -112,13 +110,7 @@ class LiveRecommendChannelAdapter(
}
}
override fun getItemCount(): Int {
return if (isFollowedCreatorLive) {
items.size + 1
} else {
items.size
}
}
override fun getItemCount() = items.size + 1
override fun getItemViewType(position: Int): Int {
return if (position == items.size) {