diff --git a/app/src/main/java/kr/co/vividnext/sodalive/home/HomeContentAdapter.kt b/app/src/main/java/kr/co/vividnext/sodalive/home/HomeContentAdapter.kt new file mode 100644 index 00000000..0586769b --- /dev/null +++ b/app/src/main/java/kr/co/vividnext/sodalive/home/HomeContentAdapter.kt @@ -0,0 +1,68 @@ +package kr.co.vividnext.sodalive.home + +import android.annotation.SuppressLint +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.recyclerview.widget.RecyclerView +import coil.load +import coil.transform.RoundedCornersTransformation +import kr.co.vividnext.sodalive.R +import kr.co.vividnext.sodalive.databinding.ItemHomeContentBinding +import kr.co.vividnext.sodalive.extensions.dpToPx + +class HomeContentAdapter( + private val onClickItem: (Long) -> Unit, +) : RecyclerView.Adapter() { + private val items = mutableListOf() + + override fun onCreateViewHolder( + parent: ViewGroup, + viewType: Int + ) = ViewHolder( + ItemHomeContentBinding.inflate( + LayoutInflater.from(parent.context), + parent, + false + ) + ) + + override fun onBindViewHolder( + holder: ViewHolder, + position: Int + ) { + holder.bind(items[position]) + } + + override fun getItemCount() = items.size + + inner class ViewHolder( + private val binding: ItemHomeContentBinding + ) : RecyclerView.ViewHolder(binding.root) { + fun bind(item: AudioContentMainItem) { + binding.ivPoint.visibility = if (item.isPointAvailable) { + View.VISIBLE + } else { + View.GONE + } + + binding.ivContentCoverImage.load(item.coverImageUrl) { + crossfade(true) + placeholder(R.drawable.ic_place_holder) + transformations(RoundedCornersTransformation(2.7f.dpToPx())) + } + + binding.tvContentTitle.text = item.title + binding.tvNickname.text = item.creatorNickname + + binding.root.setOnClickListener { onClickItem(item.contentId) } + } + } + + @SuppressLint("NotifyDataSetChanged") + fun addItems(items: List) { + this.items.clear() + this.items.addAll(items) + notifyDataSetChanged() + } +} diff --git a/app/src/main/java/kr/co/vividnext/sodalive/home/HomeContentThemeAdapter.kt b/app/src/main/java/kr/co/vividnext/sodalive/home/HomeContentThemeAdapter.kt new file mode 100644 index 00000000..3b231a15 --- /dev/null +++ b/app/src/main/java/kr/co/vividnext/sodalive/home/HomeContentThemeAdapter.kt @@ -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 + +class HomeContentThemeAdapter( + private val onClickItem: (String) -> Unit +) : RecyclerView.Adapter() { + private val themeList = mutableListOf() + private var selectedTheme = "" + + inner class ViewHolder( + private val binding: ItemHomeContentThemeBinding + ) : RecyclerView.ViewHolder(binding.root) { + @SuppressLint("NotifyDataSetChanged") + fun bind(theme: String) { + if (theme == selectedTheme || + (selectedTheme == "" && theme == "전체") + ) { + binding.tvTheme.setBackgroundResource(R.drawable.bg_round_corner_999_3bb9f1) + } else { + binding.tvTheme.setBackgroundResource(R.drawable.bg_round_corner_999_263238) + } + + binding.tvTheme.text = theme + + binding.root.setOnClickListener { + onClickItem(theme) + selectedTheme = theme + notifyDataSetChanged() + } + } + } + + @SuppressLint("NotifyDataSetChanged") + fun addItems(themeList: List) { + this.themeList.clear() + this.themeList.addAll(themeList) + notifyDataSetChanged() + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ViewHolder( + ItemHomeContentThemeBinding.inflate( + LayoutInflater.from(parent.context), + parent, + false + ) + ) + + override fun getItemCount() = themeList.size + + override fun onBindViewHolder(holder: ViewHolder, position: Int) { + holder.bind(themeList[position]) + } +} diff --git a/app/src/main/java/kr/co/vividnext/sodalive/home/HomeFragment.kt b/app/src/main/java/kr/co/vividnext/sodalive/home/HomeFragment.kt index 69886b91..f38d3b37 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/home/HomeFragment.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/home/HomeFragment.kt @@ -14,11 +14,14 @@ import android.widget.Toast import androidx.annotation.OptIn import androidx.core.content.ContextCompat import androidx.media3.common.util.UnstableApi +import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import kr.co.vividnext.sodalive.R import kr.co.vividnext.sodalive.audio_content.AudioContentPlayService +import kr.co.vividnext.sodalive.audio_content.all.AudioContentNewAllActivity import kr.co.vividnext.sodalive.audio_content.box.AudioContentBoxActivity +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.upload.AudioContentUploadActivity import kr.co.vividnext.sodalive.base.BaseFragment @@ -50,6 +53,9 @@ class HomeFragment : BaseFragment(FragmentHomeBinding::infl private lateinit var liveAdapter: HomeLiveAdapter private lateinit var creatorRankingAdapter: CreatorRankingAdapter + private lateinit var latestContentThemeAdapter: HomeContentThemeAdapter + + private lateinit var homeContentAdapter: HomeContentAdapter private val handler = Handler(Looper.getMainLooper()) @@ -301,7 +307,111 @@ class HomeFragment : BaseFragment(FragmentHomeBinding::infl } private fun setupLatestContent() { + val spSectionTitle = SpannableString(binding.tvNewContent.text) + spSectionTitle.setSpan( + ForegroundColorSpan( + ContextCompat.getColor( + requireContext(), + R.color.color_3bb9f1 + ) + ), + 0, + 2, + Spanned.SPAN_EXCLUSIVE_EXCLUSIVE + ) + binding.tvNewContent.text = spSectionTitle + latestContentThemeAdapter = HomeContentThemeAdapter { + viewModel.getLatestContentByTheme(theme = it) + } + + val rvTheme = binding.rvNewContentTheme + rvTheme.layoutManager = LinearLayoutManager( + context, + LinearLayoutManager.HORIZONTAL, + false + ) + + rvTheme.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() + } + + latestContentThemeAdapter.itemCount - 1 -> { + outRect.left = 8f.dpToPx().toInt() + outRect.right = 0 + } + + else -> { + outRect.left = 8f.dpToPx().toInt() + outRect.right = 8f.dpToPx().toInt() + } + } + } + }) + + rvTheme.adapter = latestContentThemeAdapter + + viewModel.latestContentThemeListLiveData.observe(viewLifecycleOwner) { + binding.llNewContent.visibility = View.VISIBLE + latestContentThemeAdapter.addItems(it) + } + + binding.tvNewContentAll.setOnClickListener { + if (SharedPreferenceManager.token.isNotBlank()) { + startActivity(Intent(requireContext(), AudioContentNewAllActivity::class.java)) + } else { + (requireActivity() as MainActivity).showLoginActivity() + } + } + + homeContentAdapter = HomeContentAdapter { + startActivity( + Intent(requireContext(), AudioContentDetailActivity::class.java).apply { + putExtra(Constants.EXTRA_AUDIO_CONTENT_ID, it) + } + ) + } + + val rvContent = binding.rvNewContent + 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 = homeContentAdapter + + viewModel.latestContentListLiveData.observe(viewLifecycleOwner) { + homeContentAdapter.addItems(it) + } } private fun bindData() { diff --git a/app/src/main/java/kr/co/vividnext/sodalive/home/HomeViewModel.kt b/app/src/main/java/kr/co/vividnext/sodalive/home/HomeViewModel.kt index e30a0a35..f66d3f5c 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/home/HomeViewModel.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/home/HomeViewModel.kt @@ -90,7 +90,10 @@ class HomeViewModel(private val repository: HomeRepository) : BaseViewModel() { if (it.success && data != null) { _liveListLiveData.value = data.liveList _creatorRankingLiveData.value = data.creatorRanking - _latestContentThemeListLiveData.value = data.latestContentThemeList + + val themeList = data.latestContentThemeList.toMutableList() + themeList.add(0, "전체") + _latestContentThemeListLiveData.value = themeList _latestContentListLiveData.value = data.latestContentList _eventBannerListLiveData.value = data.bannerList _originalAudioDramaListLiveData.value = data.originalAudioDramaList @@ -121,7 +124,11 @@ class HomeViewModel(private val repository: HomeRepository) : BaseViewModel() { compositeDisposable.add( repository.getLatestContentByTheme( - theme, + theme = if (theme == "전체") { + "" + } else { + theme + }, token = "Bearer ${SharedPreferenceManager.token}" ) .subscribeOn(Schedulers.io()) @@ -129,6 +136,9 @@ class HomeViewModel(private val repository: HomeRepository) : BaseViewModel() { .subscribe( { _isLoading.value = false + if (it.success && it.data != null) { + _latestContentListLiveData.value = it.data!! + } }, { _isLoading.value = false diff --git a/app/src/main/res/drawable/bg_round_corner_999_263238.xml b/app/src/main/res/drawable/bg_round_corner_999_263238.xml new file mode 100644 index 00000000..7b7f1e1a --- /dev/null +++ b/app/src/main/res/drawable/bg_round_corner_999_263238.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/app/src/main/res/drawable/bg_round_corner_999_3bb9f1.xml b/app/src/main/res/drawable/bg_round_corner_999_3bb9f1.xml new file mode 100644 index 00000000..e7cca995 --- /dev/null +++ b/app/src/main/res/drawable/bg_round_corner_999_3bb9f1.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/app/src/main/res/layout/fragment_home.xml b/app/src/main/res/layout/fragment_home.xml index afae985c..298085c5 100644 --- a/app/src/main/res/layout/fragment_home.xml +++ b/app/src/main/res/layout/fragment_home.xml @@ -130,6 +130,7 @@ android:paddingHorizontal="24dp"> + + + + + + + + + + + diff --git a/app/src/main/res/layout/item_home_content_theme.xml b/app/src/main/res/layout/item_home_content_theme.xml new file mode 100644 index 00000000..fc57cc1e --- /dev/null +++ b/app/src/main/res/layout/item_home_content_theme.xml @@ -0,0 +1,21 @@ + + + + + +