From f327eaa3f1e7b5fd40e1d448336ad3111adaa5ac Mon Sep 17 00:00:00 2001 From: Maxime Naturel Date: Thu, 10 Feb 2022 15:23:09 +0100 Subject: [PATCH] Adding item counter in add existing room to space screen --- .../home/room/list/RoomCategoryItem.kt | 3 +- .../room/list/RoomListSectionBuilderGroup.kt | 1 + .../room/list/RoomListSectionBuilderSpace.kt | 2 + .../spaces/manage/AddRoomListController.kt | 9 ++- .../spaces/manage/SpaceAddRoomFragment.kt | 70 ++++++++++++------- .../spaces/manage/SpaceAddRoomsViewModel.kt | 32 +++++++-- 6 files changed, 85 insertions(+), 32 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomCategoryItem.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomCategoryItem.kt index e9def535db..6c872e0f99 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/RoomCategoryItem.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/RoomCategoryItem.kt @@ -33,6 +33,7 @@ import im.vector.app.features.themes.ThemeUtils abstract class RoomCategoryItem : VectorEpoxyModel() { @EpoxyAttribute lateinit var title: String + @EpoxyAttribute var itemCount: Int = 0 @EpoxyAttribute var expanded: Boolean = false @EpoxyAttribute var unreadNotificationCount: Int = 0 @EpoxyAttribute var showHighlighted: Boolean = false @@ -48,7 +49,7 @@ abstract class RoomCategoryItem : VectorEpoxyModel() { holder.unreadCounterBadgeView.render(UnreadCounterBadgeView.State(unreadNotificationCount, showHighlighted)) holder.titleView.text = title with(holder.counterView) { - text = "" + text = itemCount.takeIf { it > 0 }?.toString().orEmpty() setCompoundDrawablesWithIntrinsicBounds(null, null, expandedArrowDrawable, null) } holder.rootView.onClick(listener) diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomListSectionBuilderGroup.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomListSectionBuilderGroup.kt index 005a9ef63f..ec7915ba34 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/RoomListSectionBuilderGroup.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/RoomListSectionBuilderGroup.kt @@ -76,6 +76,7 @@ class RoomListSectionBuilderGroup( val itemCountFlow = updatableFilterLivePageResult.livePagedList.asFlow() .flatMapLatest { session.getRoomCountFlow(updatableFilterLivePageResult.queryParams) } + .distinctUntilChanged() sections.add( RoomsSection( diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomListSectionBuilderSpace.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomListSectionBuilderSpace.kt index 6726243996..f82dbd43e1 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/list/RoomListSectionBuilderSpace.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/list/RoomListSectionBuilderSpace.kt @@ -95,6 +95,7 @@ class RoomListSectionBuilderSpace( val itemCountFlow = updatableFilterLivePageResult.livePagedList.asFlow() .flatMapLatest { session.getRoomCountFlow(updatableFilterLivePageResult.queryParams) } + .distinctUntilChanged() sections.add( RoomsSection( @@ -401,6 +402,7 @@ class RoomListSectionBuilderSpace( val queryParams = roomQueryParams.process(spaceFilterStrategy, appStateHandler.safeActiveSpaceId()) session.getRoomCountFlow(queryParams) } + .distinctUntilChanged() sections.add( RoomsSection( diff --git a/vector/src/main/java/im/vector/app/features/spaces/manage/AddRoomListController.kt b/vector/src/main/java/im/vector/app/features/spaces/manage/AddRoomListController.kt index 3164daf634..c2d63aa8d3 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/manage/AddRoomListController.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/manage/AddRoomListController.kt @@ -94,6 +94,12 @@ class AddRoomListController @Inject constructor( } var totalSize: Int = 0 + set(value) { + if (value != field) { + field = value + requestForcedModelBuild() + } + } var selectedItems: Map = emptyMap() set(value) { @@ -120,7 +126,8 @@ class AddRoomListController @Inject constructor( add( RoomCategoryItem_().apply { id("header") - title(host.sectionName ?: "") + title(host.sectionName.orEmpty()) + itemCount(host.totalSize) expanded(host.expanded) listener { host.expanded = !host.expanded diff --git a/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceAddRoomFragment.kt b/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceAddRoomFragment.kt index bcf0a8a949..8d6a351013 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceAddRoomFragment.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceAddRoomFragment.kt @@ -22,6 +22,8 @@ import android.view.Menu import android.view.MenuItem import android.view.View import android.view.ViewGroup +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.flowWithLifecycle import androidx.lifecycle.lifecycleScope import androidx.recyclerview.widget.ConcatAdapter import androidx.recyclerview.widget.LinearLayoutManager @@ -35,9 +37,12 @@ import im.vector.app.core.extensions.cleanup import im.vector.app.core.platform.OnBackPressed import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.databinding.FragmentSpaceAddRoomsBinding +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.debounce import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.launch import org.matrix.android.sdk.api.session.room.model.RoomSummary import reactivecircus.flowbinding.appcompat.queryTextChanges import javax.inject.Inject @@ -169,48 +174,63 @@ class SpaceAddRoomFragment @Inject constructor( } private fun setupRecyclerView() { - val concatAdapter = ConcatAdapter() - spaceEpoxyController.sectionName = getString(R.string.spaces_header) - roomEpoxyController.sectionName = getString(R.string.rooms_header) - spaceEpoxyController.listener = this - roomEpoxyController.listener = this + setupSpaceSection() + setupRoomSection() + setupDmSection() - viewModel.updatableLiveSpacePageResult.liveBoundaries.observe(viewLifecycleOwner) { + views.roomList.adapter = ConcatAdapter().apply { + addAdapter(roomEpoxyController.adapter) + addAdapter(spaceEpoxyController.adapter) + addAdapter(dmEpoxyController.adapter) + } + } + + private fun setupSpaceSection() { + spaceEpoxyController.sectionName = getString(R.string.spaces_header) + spaceEpoxyController.listener = this + viewModel.spaceUpdatableLivePageResult.liveBoundaries.observe(viewLifecycleOwner) { spaceEpoxyController.boundaryChange(it) } - viewModel.updatableLiveSpacePageResult.livePagedList.observe(viewLifecycleOwner) { - spaceEpoxyController.totalSize = it.size + viewModel.spaceUpdatableLivePageResult.livePagedList.observe(viewLifecycleOwner) { spaceEpoxyController.submitList(it) } + listenItemCount(viewModel.spaceCountFlow) { spaceEpoxyController.totalSize = it } + } - viewModel.updatableLivePageResult.liveBoundaries.observe(viewLifecycleOwner) { + private fun setupRoomSection() { + roomEpoxyController.sectionName = getString(R.string.rooms_header) + roomEpoxyController.listener = this + + viewModel.roomUpdatableLivePageResult.liveBoundaries.observe(viewLifecycleOwner) { roomEpoxyController.boundaryChange(it) } - viewModel.updatableLivePageResult.livePagedList.observe(viewLifecycleOwner) { - roomEpoxyController.totalSize = it.size + viewModel.roomUpdatableLivePageResult.livePagedList.observe(viewLifecycleOwner) { roomEpoxyController.submitList(it) } - + listenItemCount(viewModel.roomCountFlow) { roomEpoxyController.totalSize = it } views.roomList.layoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false) views.roomList.setHasFixedSize(true) + } - concatAdapter.addAdapter(roomEpoxyController.adapter) - concatAdapter.addAdapter(spaceEpoxyController.adapter) - + private fun setupDmSection() { // This controller can be disabled depending on the space type (public or not) - viewModel.updatableDMLivePageResult.liveBoundaries.observe(viewLifecycleOwner) { - dmEpoxyController.boundaryChange(it) - } - viewModel.updatableDMLivePageResult.livePagedList.observe(viewLifecycleOwner) { - dmEpoxyController.totalSize = it.size - dmEpoxyController.submitList(it) - } dmEpoxyController.sectionName = getString(R.string.direct_chats_header) dmEpoxyController.listener = this + viewModel.dmUpdatableLivePageResult.liveBoundaries.observe(viewLifecycleOwner) { + dmEpoxyController.boundaryChange(it) + } + viewModel.dmUpdatableLivePageResult.livePagedList.observe(viewLifecycleOwner) { + dmEpoxyController.submitList(it) + } + listenItemCount(viewModel.dmCountFlow) { dmEpoxyController.totalSize = it } + } - concatAdapter.addAdapter(dmEpoxyController.adapter) - - views.roomList.adapter = concatAdapter + private fun listenItemCount(itemCountFlow: Flow, onEachAction: (Int) -> Unit) { + lifecycleScope.launch { + itemCountFlow + .flowWithLifecycle(lifecycle, Lifecycle.State.STARTED) + .collect { count -> onEachAction(count) } + } } override fun onBackPressed(toolbarButton: Boolean): Boolean { diff --git a/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceAddRoomsViewModel.kt b/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceAddRoomsViewModel.kt index 383b76c946..7d99c53f23 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceAddRoomsViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceAddRoomsViewModel.kt @@ -17,6 +17,7 @@ package im.vector.app.features.spaces.manage import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.asFlow import androidx.paging.PagedList import com.airbnb.mvrx.Fail import com.airbnb.mvrx.Loading @@ -29,6 +30,9 @@ import im.vector.app.core.di.MavericksAssistedViewModelFactory import im.vector.app.core.di.hiltMavericksViewModelFactory import im.vector.app.core.platform.VectorViewModel import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.distinctUntilChanged +import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import org.matrix.android.sdk.api.query.ActiveSpaceFilter @@ -59,7 +63,7 @@ class SpaceAddRoomsViewModel @AssistedInject constructor( companion object : MavericksViewModelFactory by hiltMavericksViewModelFactory() - val updatableLiveSpacePageResult: UpdatableLivePageResult by lazy { + val spaceUpdatableLivePageResult: UpdatableLivePageResult by lazy { session.getFilteredPagedRoomSummariesLive( roomSummaryQueryParams { this.memberships = listOf(Membership.JOIN) @@ -78,7 +82,13 @@ class SpaceAddRoomsViewModel @AssistedInject constructor( ) } - val updatableLivePageResult: UpdatableLivePageResult by lazy { + val spaceCountFlow: Flow by lazy { + spaceUpdatableLivePageResult.livePagedList.asFlow() + .flatMapLatest { session.getRoomCountFlow(spaceUpdatableLivePageResult.queryParams) } + .distinctUntilChanged() + } + + val roomUpdatableLivePageResult: UpdatableLivePageResult by lazy { session.getFilteredPagedRoomSummariesLive( roomSummaryQueryParams { this.memberships = listOf(Membership.JOIN) @@ -98,7 +108,13 @@ class SpaceAddRoomsViewModel @AssistedInject constructor( ) } - val updatableDMLivePageResult: UpdatableLivePageResult by lazy { + val roomCountFlow: Flow by lazy { + roomUpdatableLivePageResult.livePagedList.asFlow() + .flatMapLatest { session.getRoomCountFlow(roomUpdatableLivePageResult.queryParams) } + .distinctUntilChanged() + } + + val dmUpdatableLivePageResult: UpdatableLivePageResult by lazy { session.getFilteredPagedRoomSummariesLive( roomSummaryQueryParams { this.memberships = listOf(Membership.JOIN) @@ -118,6 +134,12 @@ class SpaceAddRoomsViewModel @AssistedInject constructor( ) } + val dmCountFlow: Flow by lazy { + dmUpdatableLivePageResult.livePagedList.asFlow() + .flatMapLatest { session.getRoomCountFlow(dmUpdatableLivePageResult.queryParams) } + .distinctUntilChanged() + } + private val selectionList = mutableMapOf() val selectionListLiveData = MutableLiveData>() @@ -143,10 +165,10 @@ class SpaceAddRoomsViewModel @AssistedInject constructor( override fun handle(action: SpaceAddRoomActions) { when (action) { is SpaceAddRoomActions.UpdateFilter -> { - updatableLivePageResult.queryParams = updatableLivePageResult.queryParams.copy( + roomUpdatableLivePageResult.queryParams = roomUpdatableLivePageResult.queryParams.copy( displayName = QueryStringValue.Contains(action.filter, QueryStringValue.Case.INSENSITIVE) ) - updatableLivePageResult.queryParams = updatableLivePageResult.queryParams.copy( + roomUpdatableLivePageResult.queryParams = roomUpdatableLivePageResult.queryParams.copy( displayName = QueryStringValue.Contains(action.filter, QueryStringValue.Case.INSENSITIVE) ) setState {