feat(creator): 라이브 정렬 팝업을 연결한다
This commit is contained in:
@@ -13,6 +13,7 @@ import kr.co.vividnext.sodalive.v2.creator.channel.data.CreatorChannelLiveRespon
|
||||
import kr.co.vividnext.sodalive.v2.creator.channel.live.model.toLabelResId
|
||||
import kr.co.vividnext.sodalive.v2.creator.channel.live.model.toReplayUiModel
|
||||
import kr.co.vividnext.sodalive.v2.creator.channel.live.ui.CreatorChannelLiveReplayAdapter
|
||||
import kr.co.vividnext.sodalive.v2.creator.channel.live.ui.CreatorChannelLiveSortPopup
|
||||
import kr.co.vividnext.sodalive.v2.creator.channel.ui.formatCreatorChannelLiveDateTime
|
||||
import org.koin.androidx.viewmodel.ext.android.viewModel
|
||||
|
||||
@@ -25,6 +26,8 @@ class CreatorChannelLiveFragment : BaseFragment<FragmentCreatorChannelLiveBindin
|
||||
host.onCreatorChannelLiveReplayClicked(item.audioContentId)
|
||||
}
|
||||
private var lastContentLayoutKey: CreatorChannelLiveContentLayoutKey? = null
|
||||
private var sortPopup: CreatorChannelLiveSortPopup? = null
|
||||
private var currentContentState: CreatorChannelLiveUiState.Content? = null
|
||||
private val creatorId: Long by lazy { arguments?.getLong(ARG_CREATOR_ID) ?: 0L }
|
||||
private val host: Host
|
||||
get() = requireActivity() as Host
|
||||
@@ -44,6 +47,9 @@ class CreatorChannelLiveFragment : BaseFragment<FragmentCreatorChannelLiveBindin
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
sortPopup?.dismiss()
|
||||
sortPopup = null
|
||||
currentContentState = null
|
||||
binding.rvCreatorChannelLiveReplays.adapter = null
|
||||
super.onDestroyView()
|
||||
}
|
||||
@@ -59,6 +65,9 @@ class CreatorChannelLiveFragment : BaseFragment<FragmentCreatorChannelLiveBindin
|
||||
|
||||
private fun setupClickListeners() {
|
||||
binding.ivCreatorChannelLiveSort.setImageResource(R.drawable.ic_new_sort)
|
||||
binding.layoutCreatorChannelLiveSortButton.setOnClickListener {
|
||||
currentContentState?.let { state -> showSortPopup(state) }
|
||||
}
|
||||
binding.btnCreatorChannelLiveRetry.setOnClickListener {
|
||||
viewModel.retryLive()
|
||||
}
|
||||
@@ -76,6 +85,7 @@ class CreatorChannelLiveFragment : BaseFragment<FragmentCreatorChannelLiveBindin
|
||||
}
|
||||
|
||||
private fun bindLoading() = with(binding) {
|
||||
currentContentState = null
|
||||
lastContentLayoutKey = null
|
||||
layoutCreatorChannelLiveSortBar.isVisible = false
|
||||
layoutCreatorChannelLiveCurrentCard.isVisible = false
|
||||
@@ -86,6 +96,7 @@ class CreatorChannelLiveFragment : BaseFragment<FragmentCreatorChannelLiveBindin
|
||||
}
|
||||
|
||||
private fun bindEmpty() = with(binding) {
|
||||
currentContentState = null
|
||||
lastContentLayoutKey = null
|
||||
layoutCreatorChannelLiveSortBar.isVisible = false
|
||||
layoutCreatorChannelLiveCurrentCard.isVisible = false
|
||||
@@ -97,6 +108,7 @@ class CreatorChannelLiveFragment : BaseFragment<FragmentCreatorChannelLiveBindin
|
||||
}
|
||||
|
||||
private fun bindError(state: CreatorChannelLiveUiState.Error) = with(binding) {
|
||||
currentContentState = null
|
||||
lastContentLayoutKey = null
|
||||
layoutCreatorChannelLiveSortBar.isVisible = false
|
||||
layoutCreatorChannelLiveCurrentCard.isVisible = false
|
||||
@@ -109,6 +121,7 @@ class CreatorChannelLiveFragment : BaseFragment<FragmentCreatorChannelLiveBindin
|
||||
}
|
||||
|
||||
private fun bindContent(state: CreatorChannelLiveUiState.Content) = with(binding) {
|
||||
currentContentState = state
|
||||
tvCreatorChannelLiveEmptyMessage.isVisible = false
|
||||
tvCreatorChannelLiveErrorMessage.isVisible = false
|
||||
btnCreatorChannelLiveRetry.isVisible = false
|
||||
@@ -125,6 +138,15 @@ class CreatorChannelLiveFragment : BaseFragment<FragmentCreatorChannelLiveBindin
|
||||
}
|
||||
}
|
||||
|
||||
private fun showSortPopup(state: CreatorChannelLiveUiState.Content) {
|
||||
sortPopup?.dismiss()
|
||||
sortPopup = CreatorChannelLiveSortPopup(
|
||||
anchor = binding.layoutCreatorChannelLiveSortButton,
|
||||
selectedSort = state.selectedSort,
|
||||
onSortSelected = { sort -> viewModel.changeSort(sort) }
|
||||
).also { it.show() }
|
||||
}
|
||||
|
||||
private fun notifyContentChangedIfLayoutChanged(state: CreatorChannelLiveUiState.Content) {
|
||||
val contentLayoutKey = state.toContentLayoutKey()
|
||||
if (contentLayoutKey == lastContentLayoutKey) return
|
||||
|
||||
@@ -53,10 +53,36 @@ class CreatorChannelLiveFragmentLayoutTest {
|
||||
|
||||
assertNotNull(sortBar.findViewById<TextView>(R.id.tv_creator_channel_live_total_label))
|
||||
assertNotNull(sortBar.findViewById<TextView>(R.id.tv_creator_channel_live_total_count))
|
||||
assertNotNull(sortBar.findViewById<View>(R.id.layout_creator_channel_live_sort_button))
|
||||
assertNotNull(sortBar.findViewById<TextView>(R.id.tv_creator_channel_live_sort_label))
|
||||
assertNotNull(sortBar.findViewById<ImageView>(R.id.iv_creator_channel_live_sort))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `라이브 sort popup layout은 Figma 기준 option row와 선택 배경을 제공한다`() {
|
||||
val popup = inflateView(R.layout.view_creator_channel_live_sort_menu)
|
||||
val popupLayout = projectFile(
|
||||
"app/src/main/res/layout/view_creator_channel_live_sort_menu.xml"
|
||||
).readText()
|
||||
val popupBackground = projectFile(
|
||||
"app/src/main/res/drawable/bg_creator_channel_live_sort_popup.xml"
|
||||
).readText()
|
||||
val selectedBackground = projectFile(
|
||||
"app/src/main/res/drawable/bg_creator_channel_live_sort_selected.xml"
|
||||
).readText()
|
||||
|
||||
assertNotNull(popup.findViewById<View>(R.id.layout_creator_channel_live_sort_options))
|
||||
assertTrue(popupLayout.contains("@drawable/bg_creator_channel_live_sort_popup"))
|
||||
assertTrue(popupLayout.contains("@+id/layout_creator_channel_live_sort_options"))
|
||||
assertTrue(popupLayout.contains("android:paddingHorizontal=\"@dimen/spacing_12\""))
|
||||
assertTrue(popupLayout.contains("android:paddingVertical=\"@dimen/spacing_8\""))
|
||||
assertTrue(popupLayout.contains("android:fontFamily=\"@font/medium\""))
|
||||
assertTrue(popupBackground.contains("android:radius=\"@dimen/radius_14\""))
|
||||
assertTrue(popupBackground.contains("android:color=\"@color/gray_900\""))
|
||||
assertTrue(popupBackground.contains("android:color=\"@color/gray_700\""))
|
||||
assertTrue(selectedBackground.contains("android:color=\"@color/gray_800\""))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `라이브 다시듣기 item layout은 썸네일 tag title duration action 영역을 제공한다`() {
|
||||
val item = inflateView(R.layout.item_creator_channel_live_replay)
|
||||
@@ -139,6 +165,11 @@ class CreatorChannelLiveFragmentLayoutTest {
|
||||
|
||||
assertTrue(layout.contains("android:layout_height=\"match_parent\""))
|
||||
assertTrue(fragment.contains("R.drawable.ic_new_sort"))
|
||||
assertTrue(fragment.contains("CreatorChannelLiveSortPopup"))
|
||||
assertTrue(fragment.contains("layoutCreatorChannelLiveSortButton.setOnClickListener"))
|
||||
assertTrue(fragment.contains("showSortPopup"))
|
||||
assertTrue(fragment.contains("viewModel.changeSort(sort)"))
|
||||
assertTrue(fragment.contains("sortPopup?.dismiss()"))
|
||||
assertTrue(fragment.contains("super.onViewCreated(view, savedInstanceState)\n bindLoading()"))
|
||||
assertTrue(fragment.contains("retryLive()"))
|
||||
assertTrue(fragment.contains("fun onCreatorChannelLiveTabSelected()"))
|
||||
@@ -165,6 +196,24 @@ class CreatorChannelLiveFragmentLayoutTest {
|
||||
assertTrue(adapter.contains("layoutCreatorChannelLiveReplayActionText.isVisible = true"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `라이브 sort popup source는 outside dismiss와 화면 밖 보정 및 같은 정렬 dismiss를 포함한다`() {
|
||||
val popup = projectFile(
|
||||
"app/src/main/java/kr/co/vividnext/sodalive/v2/creator/channel/live/ui/CreatorChannelLiveSortPopup.kt"
|
||||
).readText()
|
||||
|
||||
assertTrue(popup.contains("PopupWindow"))
|
||||
assertTrue(popup.contains("isOutsideTouchable = true"))
|
||||
assertTrue(popup.contains("isFocusable = true"))
|
||||
assertTrue(popup.contains("toSortOptionUiModel"))
|
||||
assertTrue(popup.contains("if (option.sort != selectedSort)"))
|
||||
assertTrue(popup.contains("onSortSelected(option.sort)"))
|
||||
assertTrue(popup.contains("dismiss()"))
|
||||
assertTrue(popup.contains("calculateHorizontalOffset"))
|
||||
assertTrue(popup.contains("visibleDisplayFrame"))
|
||||
assertTrue(popup.contains("showAsDropDown"))
|
||||
}
|
||||
|
||||
private fun inflateView(layoutResId: Int): View {
|
||||
val context = ApplicationProvider.getApplicationContext<Context>()
|
||||
return LayoutInflater.from(context).inflate(layoutResId, null, false)
|
||||
|
||||
Reference in New Issue
Block a user