Adding item counter in add existing room to space screen

This commit is contained in:
Maxime Naturel 2022-02-10 15:23:09 +01:00
parent 20749e04cb
commit f327eaa3f1
6 changed files with 85 additions and 32 deletions

View File

@ -33,6 +33,7 @@ import im.vector.app.features.themes.ThemeUtils
abstract class RoomCategoryItem : VectorEpoxyModel<RoomCategoryItem.Holder>() { abstract class RoomCategoryItem : VectorEpoxyModel<RoomCategoryItem.Holder>() {
@EpoxyAttribute lateinit var title: String @EpoxyAttribute lateinit var title: String
@EpoxyAttribute var itemCount: Int = 0
@EpoxyAttribute var expanded: Boolean = false @EpoxyAttribute var expanded: Boolean = false
@EpoxyAttribute var unreadNotificationCount: Int = 0 @EpoxyAttribute var unreadNotificationCount: Int = 0
@EpoxyAttribute var showHighlighted: Boolean = false @EpoxyAttribute var showHighlighted: Boolean = false
@ -48,7 +49,7 @@ abstract class RoomCategoryItem : VectorEpoxyModel<RoomCategoryItem.Holder>() {
holder.unreadCounterBadgeView.render(UnreadCounterBadgeView.State(unreadNotificationCount, showHighlighted)) holder.unreadCounterBadgeView.render(UnreadCounterBadgeView.State(unreadNotificationCount, showHighlighted))
holder.titleView.text = title holder.titleView.text = title
with(holder.counterView) { with(holder.counterView) {
text = "" text = itemCount.takeIf { it > 0 }?.toString().orEmpty()
setCompoundDrawablesWithIntrinsicBounds(null, null, expandedArrowDrawable, null) setCompoundDrawablesWithIntrinsicBounds(null, null, expandedArrowDrawable, null)
} }
holder.rootView.onClick(listener) holder.rootView.onClick(listener)

View File

@ -76,6 +76,7 @@ class RoomListSectionBuilderGroup(
val itemCountFlow = updatableFilterLivePageResult.livePagedList.asFlow() val itemCountFlow = updatableFilterLivePageResult.livePagedList.asFlow()
.flatMapLatest { session.getRoomCountFlow(updatableFilterLivePageResult.queryParams) } .flatMapLatest { session.getRoomCountFlow(updatableFilterLivePageResult.queryParams) }
.distinctUntilChanged()
sections.add( sections.add(
RoomsSection( RoomsSection(

View File

@ -95,6 +95,7 @@ class RoomListSectionBuilderSpace(
val itemCountFlow = updatableFilterLivePageResult.livePagedList.asFlow() val itemCountFlow = updatableFilterLivePageResult.livePagedList.asFlow()
.flatMapLatest { session.getRoomCountFlow(updatableFilterLivePageResult.queryParams) } .flatMapLatest { session.getRoomCountFlow(updatableFilterLivePageResult.queryParams) }
.distinctUntilChanged()
sections.add( sections.add(
RoomsSection( RoomsSection(
@ -401,6 +402,7 @@ class RoomListSectionBuilderSpace(
val queryParams = roomQueryParams.process(spaceFilterStrategy, appStateHandler.safeActiveSpaceId()) val queryParams = roomQueryParams.process(spaceFilterStrategy, appStateHandler.safeActiveSpaceId())
session.getRoomCountFlow(queryParams) session.getRoomCountFlow(queryParams)
} }
.distinctUntilChanged()
sections.add( sections.add(
RoomsSection( RoomsSection(

View File

@ -94,6 +94,12 @@ class AddRoomListController @Inject constructor(
} }
var totalSize: Int = 0 var totalSize: Int = 0
set(value) {
if (value != field) {
field = value
requestForcedModelBuild()
}
}
var selectedItems: Map<String, Boolean> = emptyMap() var selectedItems: Map<String, Boolean> = emptyMap()
set(value) { set(value) {
@ -120,7 +126,8 @@ class AddRoomListController @Inject constructor(
add( add(
RoomCategoryItem_().apply { RoomCategoryItem_().apply {
id("header") id("header")
title(host.sectionName ?: "") title(host.sectionName.orEmpty())
itemCount(host.totalSize)
expanded(host.expanded) expanded(host.expanded)
listener { listener {
host.expanded = !host.expanded host.expanded = !host.expanded

View File

@ -22,6 +22,8 @@ import android.view.Menu
import android.view.MenuItem import android.view.MenuItem
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.flowWithLifecycle
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.ConcatAdapter import androidx.recyclerview.widget.ConcatAdapter
import androidx.recyclerview.widget.LinearLayoutManager 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.OnBackPressed
import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.core.platform.VectorBaseFragment
import im.vector.app.databinding.FragmentSpaceAddRoomsBinding 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.debounce
import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import org.matrix.android.sdk.api.session.room.model.RoomSummary import org.matrix.android.sdk.api.session.room.model.RoomSummary
import reactivecircus.flowbinding.appcompat.queryTextChanges import reactivecircus.flowbinding.appcompat.queryTextChanges
import javax.inject.Inject import javax.inject.Inject
@ -169,48 +174,63 @@ class SpaceAddRoomFragment @Inject constructor(
} }
private fun setupRecyclerView() { private fun setupRecyclerView() {
val concatAdapter = ConcatAdapter() setupSpaceSection()
spaceEpoxyController.sectionName = getString(R.string.spaces_header) setupRoomSection()
roomEpoxyController.sectionName = getString(R.string.rooms_header) setupDmSection()
spaceEpoxyController.listener = this
roomEpoxyController.listener = this
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) spaceEpoxyController.boundaryChange(it)
} }
viewModel.updatableLiveSpacePageResult.livePagedList.observe(viewLifecycleOwner) { viewModel.spaceUpdatableLivePageResult.livePagedList.observe(viewLifecycleOwner) {
spaceEpoxyController.totalSize = it.size
spaceEpoxyController.submitList(it) 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) roomEpoxyController.boundaryChange(it)
} }
viewModel.updatableLivePageResult.livePagedList.observe(viewLifecycleOwner) { viewModel.roomUpdatableLivePageResult.livePagedList.observe(viewLifecycleOwner) {
roomEpoxyController.totalSize = it.size
roomEpoxyController.submitList(it) roomEpoxyController.submitList(it)
} }
listenItemCount(viewModel.roomCountFlow) { roomEpoxyController.totalSize = it }
views.roomList.layoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false) views.roomList.layoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)
views.roomList.setHasFixedSize(true) views.roomList.setHasFixedSize(true)
}
concatAdapter.addAdapter(roomEpoxyController.adapter) private fun setupDmSection() {
concatAdapter.addAdapter(spaceEpoxyController.adapter)
// This controller can be disabled depending on the space type (public or not) // 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.sectionName = getString(R.string.direct_chats_header)
dmEpoxyController.listener = this 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) private fun listenItemCount(itemCountFlow: Flow<Int>, onEachAction: (Int) -> Unit) {
lifecycleScope.launch {
views.roomList.adapter = concatAdapter itemCountFlow
.flowWithLifecycle(lifecycle, Lifecycle.State.STARTED)
.collect { count -> onEachAction(count) }
}
} }
override fun onBackPressed(toolbarButton: Boolean): Boolean { override fun onBackPressed(toolbarButton: Boolean): Boolean {

View File

@ -17,6 +17,7 @@
package im.vector.app.features.spaces.manage package im.vector.app.features.spaces.manage
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.asFlow
import androidx.paging.PagedList import androidx.paging.PagedList
import com.airbnb.mvrx.Fail import com.airbnb.mvrx.Fail
import com.airbnb.mvrx.Loading 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.di.hiltMavericksViewModelFactory
import im.vector.app.core.platform.VectorViewModel import im.vector.app.core.platform.VectorViewModel
import kotlinx.coroutines.Dispatchers 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.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import org.matrix.android.sdk.api.query.ActiveSpaceFilter import org.matrix.android.sdk.api.query.ActiveSpaceFilter
@ -59,7 +63,7 @@ class SpaceAddRoomsViewModel @AssistedInject constructor(
companion object : MavericksViewModelFactory<SpaceAddRoomsViewModel, SpaceAddRoomsState> by hiltMavericksViewModelFactory() companion object : MavericksViewModelFactory<SpaceAddRoomsViewModel, SpaceAddRoomsState> by hiltMavericksViewModelFactory()
val updatableLiveSpacePageResult: UpdatableLivePageResult by lazy { val spaceUpdatableLivePageResult: UpdatableLivePageResult by lazy {
session.getFilteredPagedRoomSummariesLive( session.getFilteredPagedRoomSummariesLive(
roomSummaryQueryParams { roomSummaryQueryParams {
this.memberships = listOf(Membership.JOIN) this.memberships = listOf(Membership.JOIN)
@ -78,7 +82,13 @@ class SpaceAddRoomsViewModel @AssistedInject constructor(
) )
} }
val updatableLivePageResult: UpdatableLivePageResult by lazy { val spaceCountFlow: Flow<Int> by lazy {
spaceUpdatableLivePageResult.livePagedList.asFlow()
.flatMapLatest { session.getRoomCountFlow(spaceUpdatableLivePageResult.queryParams) }
.distinctUntilChanged()
}
val roomUpdatableLivePageResult: UpdatableLivePageResult by lazy {
session.getFilteredPagedRoomSummariesLive( session.getFilteredPagedRoomSummariesLive(
roomSummaryQueryParams { roomSummaryQueryParams {
this.memberships = listOf(Membership.JOIN) this.memberships = listOf(Membership.JOIN)
@ -98,7 +108,13 @@ class SpaceAddRoomsViewModel @AssistedInject constructor(
) )
} }
val updatableDMLivePageResult: UpdatableLivePageResult by lazy { val roomCountFlow: Flow<Int> by lazy {
roomUpdatableLivePageResult.livePagedList.asFlow()
.flatMapLatest { session.getRoomCountFlow(roomUpdatableLivePageResult.queryParams) }
.distinctUntilChanged()
}
val dmUpdatableLivePageResult: UpdatableLivePageResult by lazy {
session.getFilteredPagedRoomSummariesLive( session.getFilteredPagedRoomSummariesLive(
roomSummaryQueryParams { roomSummaryQueryParams {
this.memberships = listOf(Membership.JOIN) this.memberships = listOf(Membership.JOIN)
@ -118,6 +134,12 @@ class SpaceAddRoomsViewModel @AssistedInject constructor(
) )
} }
val dmCountFlow: Flow<Int> by lazy {
dmUpdatableLivePageResult.livePagedList.asFlow()
.flatMapLatest { session.getRoomCountFlow(dmUpdatableLivePageResult.queryParams) }
.distinctUntilChanged()
}
private val selectionList = mutableMapOf<String, Boolean>() private val selectionList = mutableMapOf<String, Boolean>()
val selectionListLiveData = MutableLiveData<Map<String, Boolean>>() val selectionListLiveData = MutableLiveData<Map<String, Boolean>>()
@ -143,10 +165,10 @@ class SpaceAddRoomsViewModel @AssistedInject constructor(
override fun handle(action: SpaceAddRoomActions) { override fun handle(action: SpaceAddRoomActions) {
when (action) { when (action) {
is SpaceAddRoomActions.UpdateFilter -> { is SpaceAddRoomActions.UpdateFilter -> {
updatableLivePageResult.queryParams = updatableLivePageResult.queryParams.copy( roomUpdatableLivePageResult.queryParams = roomUpdatableLivePageResult.queryParams.copy(
displayName = QueryStringValue.Contains(action.filter, QueryStringValue.Case.INSENSITIVE) 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) displayName = QueryStringValue.Contains(action.filter, QueryStringValue.Case.INSENSITIVE)
) )
setState { setState {