Merge pull request #5616 from vector-im/hotfix/fre/collapse_rooms_section

Fix rooms section collapsing
This commit is contained in:
ganfra 2022-03-24 16:04:16 +01:00 committed by GitHub
commit 81aa42a8e8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 64 additions and 48 deletions

1
changelog.d/5616.bugfix Normal file
View File

@ -0,0 +1 @@
Fix inconsistencies between the arrow visibility and the collapse action on the room sections

View File

@ -148,8 +148,10 @@ class RoomListFragment @Inject constructor(
} }
private fun refreshCollapseStates() { private fun refreshCollapseStates() {
val sectionsCount = adapterInfosList.count { !it.sectionHeaderAdapter.roomsSectionData.isHidden }
roomListViewModel.sections.forEachIndexed { index, roomsSection -> roomListViewModel.sections.forEachIndexed { index, roomsSection ->
val actualBlock = adapterInfosList[index] val actualBlock = adapterInfosList[index]
val isRoomSectionCollapsable = sectionsCount > 1
val isRoomSectionExpanded = roomsSection.isExpanded.value.orTrue() val isRoomSectionExpanded = roomsSection.isExpanded.value.orTrue()
if (actualBlock.section.isExpanded && !isRoomSectionExpanded) { if (actualBlock.section.isExpanded && !isRoomSectionExpanded) {
// mark controller as collapsed // mark controller as collapsed
@ -158,12 +160,18 @@ class RoomListFragment @Inject constructor(
// we must expand! // we must expand!
actualBlock.contentEpoxyController.setCollapsed(false) actualBlock.contentEpoxyController.setCollapsed(false)
} }
actualBlock.section = actualBlock.section.copy( actualBlock.section = actualBlock.section.copy(isExpanded = isRoomSectionExpanded)
isExpanded = isRoomSectionExpanded actualBlock.sectionHeaderAdapter.updateSection {
) it.copy(
actualBlock.sectionHeaderAdapter.updateSection( isExpanded = isRoomSectionExpanded,
actualBlock.sectionHeaderAdapter.roomsSectionData.copy(isExpanded = isRoomSectionExpanded) isCollapsable = isRoomSectionCollapsable
) )
}
if (!isRoomSectionExpanded && !isRoomSectionCollapsable) {
// force expand if the section is not collapsable
roomListViewModel.handle(RoomListAction.ToggleSection(roomsSection))
}
} }
} }
@ -271,33 +279,36 @@ class RoomListFragment @Inject constructor(
val concatAdapter = ConcatAdapter() val concatAdapter = ConcatAdapter()
roomListViewModel.sections.forEach { section -> roomListViewModel.sections.forEachIndexed { index, section ->
val sectionAdapter = SectionHeaderAdapter { val sectionAdapter = SectionHeaderAdapter(SectionHeaderAdapter.RoomsSectionData(section.sectionName)) {
roomListViewModel.handle(RoomListAction.ToggleSection(section)) if (adapterInfosList[index].sectionHeaderAdapter.roomsSectionData.isCollapsable) {
}.also { roomListViewModel.handle(RoomListAction.ToggleSection(section))
it.updateSection(SectionHeaderAdapter.RoomsSectionData(section.sectionName)) }
} }
val contentAdapter = val contentAdapter =
when { when {
section.livePages != null -> { section.livePages != null -> {
pagedControllerFactory.createRoomSummaryPagedController() pagedControllerFactory.createRoomSummaryPagedController()
.also { controller -> .also { controller ->
section.livePages.observe(viewLifecycleOwner) { pl -> section.livePages.observe(viewLifecycleOwner) { pl ->
controller.submitList(pl) controller.submitList(pl)
sectionAdapter.updateSection(sectionAdapter.roomsSectionData.copy( sectionAdapter.updateSection {
isHidden = pl.isEmpty(), it.copy(
isLoading = false isHidden = pl.isEmpty(),
)) isLoading = false
)
}
refreshCollapseStates()
checkEmptyState() checkEmptyState()
} }
observeItemCount(section, sectionAdapter) observeItemCount(section, sectionAdapter)
section.notificationCount.observe(viewLifecycleOwner) { counts -> section.notificationCount.observe(viewLifecycleOwner) { counts ->
sectionAdapter.updateSection(sectionAdapter.roomsSectionData.copy( sectionAdapter.updateSection {
notificationCount = counts.totalCount, it.copy(
isHighlighted = counts.isHighlight, notificationCount = counts.totalCount,
shouldShowExpandedArrow = shouldShowExpendedArrow() isHighlighted = counts.isHighlight,
)) )
}
} }
section.isExpanded.observe(viewLifecycleOwner) { _ -> section.isExpanded.observe(viewLifecycleOwner) { _ ->
refreshCollapseStates() refreshCollapseStates()
@ -310,10 +321,13 @@ class RoomListFragment @Inject constructor(
.also { controller -> .also { controller ->
section.liveSuggested.observe(viewLifecycleOwner) { info -> section.liveSuggested.observe(viewLifecycleOwner) { info ->
controller.setData(info) controller.setData(info)
sectionAdapter.updateSection(sectionAdapter.roomsSectionData.copy( sectionAdapter.updateSection {
isHidden = info.rooms.isEmpty(), it.copy(
isLoading = false isHidden = info.rooms.isEmpty(),
)) isLoading = false
)
}
refreshCollapseStates()
checkEmptyState() checkEmptyState()
} }
observeItemCount(section, sectionAdapter) observeItemCount(section, sectionAdapter)
@ -328,20 +342,23 @@ class RoomListFragment @Inject constructor(
.also { controller -> .also { controller ->
section.liveList?.observe(viewLifecycleOwner) { list -> section.liveList?.observe(viewLifecycleOwner) { list ->
controller.setData(list) controller.setData(list)
sectionAdapter.updateSection(sectionAdapter.roomsSectionData.copy( sectionAdapter.updateSection {
isHidden = list.isEmpty(), it.copy(
isLoading = false, isHidden = list.isEmpty(),
shouldShowExpandedArrow = shouldShowExpendedArrow() isLoading = false,
)) )
}
refreshCollapseStates()
checkEmptyState() checkEmptyState()
} }
observeItemCount(section, sectionAdapter) observeItemCount(section, sectionAdapter)
section.notificationCount.observe(viewLifecycleOwner) { counts -> section.notificationCount.observe(viewLifecycleOwner) { counts ->
sectionAdapter.updateSection(sectionAdapter.roomsSectionData.copy( sectionAdapter.updateSection {
notificationCount = counts.totalCount, it.copy(
isHighlighted = counts.isHighlight, notificationCount = counts.totalCount,
shouldShowExpandedArrow = shouldShowExpendedArrow() isHighlighted = counts.isHighlight
)) )
}
} }
section.isExpanded.observe(viewLifecycleOwner) { _ -> section.isExpanded.observe(viewLifecycleOwner) { _ ->
refreshCollapseStates() refreshCollapseStates()
@ -389,9 +406,9 @@ class RoomListFragment @Inject constructor(
section.itemCount section.itemCount
.flowWithLifecycle(lifecycle, Lifecycle.State.STARTED) .flowWithLifecycle(lifecycle, Lifecycle.State.STARTED)
.collect { count -> .collect { count ->
sectionAdapter.updateSection( sectionAdapter.updateSection {
sectionAdapter.roomsSectionData.copy(itemCount = count) it.copy(itemCount = count)
) }
} }
} }
} }
@ -448,10 +465,6 @@ class RoomListFragment @Inject constructor(
footerController.setData(state) footerController.setData(state)
} }
private fun shouldShowExpendedArrow(): Boolean {
return adapterInfosList.filter { !it.sectionHeaderAdapter.roomsSectionData.isHidden }.size >= 2
}
private fun checkEmptyState() { private fun checkEmptyState() {
val shouldShowEmpty = adapterInfosList.all { it.sectionHeaderAdapter.roomsSectionData.isHidden } && val shouldShowEmpty = adapterInfosList.all { it.sectionHeaderAdapter.roomsSectionData.isHidden } &&
!adapterInfosList.any { it.sectionHeaderAdapter.roomsSectionData.isLoading } !adapterInfosList.any { it.sectionHeaderAdapter.roomsSectionData.isLoading }

View File

@ -29,6 +29,7 @@ import im.vector.app.databinding.ItemRoomCategoryBinding
import im.vector.app.features.themes.ThemeUtils import im.vector.app.features.themes.ThemeUtils
class SectionHeaderAdapter constructor( class SectionHeaderAdapter constructor(
roomsSectionData: RoomsSectionData,
private val onClickAction: ClickListener private val onClickAction: ClickListener
) : RecyclerView.Adapter<SectionHeaderAdapter.VH>() { ) : RecyclerView.Adapter<SectionHeaderAdapter.VH>() {
@ -41,14 +42,15 @@ class SectionHeaderAdapter constructor(
val isHidden: Boolean = true, val isHidden: Boolean = true,
// This will be false until real data has been submitted once // This will be false until real data has been submitted once
val isLoading: Boolean = true, val isLoading: Boolean = true,
val shouldShowExpandedArrow: Boolean = false val isCollapsable: Boolean = false
) )
lateinit var roomsSectionData: RoomsSectionData var roomsSectionData: RoomsSectionData = roomsSectionData
private set private set
fun updateSection(newRoomsSectionData: RoomsSectionData) { fun updateSection(block: (RoomsSectionData) -> RoomsSectionData) {
if (!::roomsSectionData.isInitialized || newRoomsSectionData != roomsSectionData) { val newRoomsSectionData = block(roomsSectionData)
if (roomsSectionData != newRoomsSectionData) {
roomsSectionData = newRoomsSectionData roomsSectionData = newRoomsSectionData
notifyDataSetChanged() notifyDataSetChanged()
} }
@ -84,7 +86,7 @@ class SectionHeaderAdapter constructor(
fun bind(roomsSectionData: RoomsSectionData) { fun bind(roomsSectionData: RoomsSectionData) {
binding.roomCategoryTitleView.text = roomsSectionData.name binding.roomCategoryTitleView.text = roomsSectionData.name
val tintColor = ThemeUtils.getColor(binding.root.context, R.attr.vctr_content_secondary) val tintColor = ThemeUtils.getColor(binding.root.context, R.attr.vctr_content_secondary)
if (roomsSectionData.shouldShowExpandedArrow) { if (roomsSectionData.isCollapsable) {
binding.roomCategoryCounterView.visibility = View.VISIBLE binding.roomCategoryCounterView.visibility = View.VISIBLE
val expandedArrowDrawableRes = if (roomsSectionData.isExpanded) R.drawable.ic_expand_more else R.drawable.ic_expand_less val expandedArrowDrawableRes = if (roomsSectionData.isExpanded) R.drawable.ic_expand_more else R.drawable.ic_expand_less
val expandedArrowDrawable = ContextCompat.getDrawable(binding.root.context, expandedArrowDrawableRes)?.also { val expandedArrowDrawable = ContextCompat.getDrawable(binding.root.context, expandedArrowDrawableRes)?.also {