RoomList: more fixes on count

This commit is contained in:
ganfra 2022-03-24 18:50:33 +01:00
parent 87438085c6
commit 04b136e3e4
6 changed files with 179 additions and 176 deletions

View file

@ -18,7 +18,6 @@ package org.matrix.android.sdk.api.session.room
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.paging.PagedList import androidx.paging.PagedList
import kotlinx.coroutines.flow.Flow
import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.events.model.Event
import org.matrix.android.sdk.api.session.room.members.ChangeMembershipState import org.matrix.android.sdk.api.session.room.members.ChangeMembershipState
import org.matrix.android.sdk.api.session.room.model.Membership import org.matrix.android.sdk.api.session.room.model.Membership
@ -218,7 +217,8 @@ interface RoomService {
sortOrder: RoomSortOrder = RoomSortOrder.ACTIVITY): UpdatableLivePageResult sortOrder: RoomSortOrder = RoomSortOrder.ACTIVITY): UpdatableLivePageResult
/** /**
* Retrieve a LiveData on the number of rooms. * Return a LiveData on the number of rooms
* @param queryParams parameters to query the room summaries. It can be use to keep only joined rooms, for instance.
*/ */
fun getRoomCountLive(queryParams: RoomSummaryQueryParams): LiveData<Int> fun getRoomCountLive(queryParams: RoomSummaryQueryParams): LiveData<Int>

View file

@ -20,7 +20,6 @@ import androidx.lifecycle.LiveData
import androidx.lifecycle.Transformations import androidx.lifecycle.Transformations
import androidx.paging.PagedList import androidx.paging.PagedList
import com.zhuinden.monarchy.Monarchy import com.zhuinden.monarchy.Monarchy
import kotlinx.coroutines.flow.Flow
import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.events.model.Event
import org.matrix.android.sdk.api.session.room.Room import org.matrix.android.sdk.api.session.room.Room
import org.matrix.android.sdk.api.session.room.RoomService import org.matrix.android.sdk.api.session.room.RoomService

View file

@ -241,7 +241,7 @@ internal class RoomSummaryDataSource @Inject constructor(
roomSummariesQuery(it, queryParams) roomSummariesQuery(it, queryParams)
} }
return Transformations.map(liveRooms) { return Transformations.map(liveRooms) {
it.realmResults.count() it.realmResults.where().count().toInt()
} }
} }

View file

@ -53,6 +53,7 @@ import im.vector.app.features.home.room.list.actions.RoomListQuickActionsSharedA
import im.vector.app.features.home.room.list.widget.NotifsFabMenuView import im.vector.app.features.home.room.list.widget.NotifsFabMenuView
import im.vector.app.features.notifications.NotificationDrawerManager import im.vector.app.features.notifications.NotificationDrawerManager
import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.filter
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 kotlinx.coroutines.launch
@ -287,7 +288,7 @@ class RoomListFragment @Inject constructor(
} }
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 ->
@ -405,6 +406,7 @@ class RoomListFragment @Inject constructor(
lifecycleScope.launch { lifecycleScope.launch {
section.itemCount section.itemCount
.flowWithLifecycle(lifecycle, Lifecycle.State.STARTED) .flowWithLifecycle(lifecycle, Lifecycle.State.STARTED)
.filter { it > 0 }
.collect { count -> .collect { count ->
sectionAdapter.updateSection { sectionAdapter.updateSection {
it.copy(itemCount = count) it.copy(itemCount = count)

View file

@ -70,22 +70,20 @@ class RoomListSectionBuilderGroup(
}, },
{ qpm -> { qpm ->
val name = stringProvider.getString(R.string.bottom_action_rooms) val name = stringProvider.getString(R.string.bottom_action_rooms)
session.getFilteredPagedRoomSummariesLive(qpm) val updatableFilterLivePageResult = session.getFilteredPagedRoomSummariesLive(qpm)
.let { updatableFilterLivePageResult -> onUpdatable(updatableFilterLivePageResult)
onUpdatable(updatableFilterLivePageResult)
val itemCountFlow = updatableFilterLivePageResult.livePagedList.asFlow() val itemCountFlow = updatableFilterLivePageResult.livePagedList.asFlow()
.flatMapLatest { session.getRoomCountLive(updatableFilterLivePageResult.queryParams).asFlow() } .flatMapLatest { session.getRoomCountLive(updatableFilterLivePageResult.queryParams).asFlow() }
.distinctUntilChanged() .distinctUntilChanged()
sections.add( sections.add(
RoomsSection( RoomsSection(
sectionName = name, sectionName = name,
livePages = updatableFilterLivePageResult.livePagedList, livePages = updatableFilterLivePageResult.livePagedList,
itemCount = itemCountFlow itemCount = itemCountFlow
) )
) )
}
} }
) )
} }
@ -252,37 +250,33 @@ class RoomListSectionBuilderGroup(
@StringRes nameRes: Int, @StringRes nameRes: Int,
notifyOfLocalEcho: Boolean = false, notifyOfLocalEcho: Boolean = false,
query: (RoomSummaryQueryParams.Builder) -> Unit) { query: (RoomSummaryQueryParams.Builder) -> Unit) {
withQueryParams( withQueryParams(query) { roomQueryParams ->
{ query.invoke(it) }, val name = stringProvider.getString(nameRes)
{ roomQueryParams -> session.getFilteredPagedRoomSummariesLive(roomQueryParams)
val name = stringProvider.getString(nameRes) .also {
session.getFilteredPagedRoomSummariesLive(roomQueryParams) activeSpaceUpdaters.add(it)
.also { }.livePagedList
activeSpaceUpdaters.add(it) .let { livePagedList ->
}.livePagedList // use it also as a source to update count
.let { livePagedList -> livePagedList.asFlow()
// use it also as a source to update count .onEach {
livePagedList.asFlow() sections.find { it.sectionName == name }
.onEach { ?.notificationCount
sections.find { it.sectionName == name } ?.postValue(session.getNotificationCountForRooms(roomQueryParams))
?.notificationCount }
?.postValue(session.getNotificationCountForRooms(roomQueryParams)) .flowOn(Dispatchers.Default)
} .launchIn(coroutineScope)
.flowOn(Dispatchers.Default)
.launchIn(coroutineScope)
sections.add( sections.add(
RoomsSection( RoomsSection(
sectionName = name, sectionName = name,
livePages = livePagedList, livePages = livePagedList,
notifyOfLocalEcho = notifyOfLocalEcho, notifyOfLocalEcho = notifyOfLocalEcho,
itemCount = session.getRoomCountLive(roomQueryParams).asFlow() itemCount = session.getRoomCountLive(roomQueryParams).asFlow()
)
) )
} )
} }
}
)
} }
private fun withQueryParams(builder: (RoomSummaryQueryParams.Builder) -> Unit, block: (RoomSummaryQueryParams) -> Unit) { private fun withQueryParams(builder: (RoomSummaryQueryParams.Builder) -> Unit, block: (RoomSummaryQueryParams) -> Unit) {

View file

@ -32,6 +32,7 @@ import im.vector.app.features.invite.showInvites
import im.vector.app.space import im.vector.app.space
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flatMapLatest
@ -40,6 +41,7 @@ import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.update
import org.matrix.android.sdk.api.extensions.tryOrNull import org.matrix.android.sdk.api.extensions.tryOrNull
import org.matrix.android.sdk.api.query.ActiveSpaceFilter import org.matrix.android.sdk.api.query.ActiveSpaceFilter
import org.matrix.android.sdk.api.query.RoomCategoryFilter import org.matrix.android.sdk.api.query.RoomCategoryFilter
@ -83,64 +85,10 @@ class RoomListSectionBuilderSpace(
} }
RoomListDisplayMode.FILTERED -> { RoomListDisplayMode.FILTERED -> {
// Used when searching for rooms // Used when searching for rooms
withQueryParams( buildFilteredSection(sections)
{
it.memberships = Membership.activeMemberships()
},
{ qpm ->
val name = stringProvider.getString(R.string.bottom_action_rooms)
session.getFilteredPagedRoomSummariesLive(qpm)
.let { updatableFilterLivePageResult ->
onUpdatable(updatableFilterLivePageResult)
val itemCountFlow = updatableFilterLivePageResult.livePagedList.asFlow()
.flatMapLatest { session.getRoomCountLive(updatableFilterLivePageResult.queryParams).asFlow() }
.distinctUntilChanged()
sections.add(
RoomsSection(
sectionName = name,
livePages = updatableFilterLivePageResult.livePagedList,
itemCount = itemCountFlow
)
)
}
}
)
} }
RoomListDisplayMode.NOTIFICATIONS -> { RoomListDisplayMode.NOTIFICATIONS -> {
if (autoAcceptInvites.showInvites()) { buildNotificationsSection(sections, activeSpaceAwareQueries)
addSection(
sections = sections,
activeSpaceUpdaters = activeSpaceAwareQueries,
nameRes = R.string.invitations_header,
notifyOfLocalEcho = true,
spaceFilterStrategy = if (onlyOrphansInHome) {
RoomListViewModel.SpaceFilterStrategy.ORPHANS_IF_SPACE_NULL
} else {
RoomListViewModel.SpaceFilterStrategy.ALL_IF_SPACE_NULL
},
countRoomAsNotif = true
) {
it.memberships = listOf(Membership.INVITE)
it.roomCategoryFilter = RoomCategoryFilter.ALL
}
}
addSection(
sections = sections,
activeSpaceUpdaters = activeSpaceAwareQueries,
nameRes = R.string.bottom_action_rooms,
notifyOfLocalEcho = false,
spaceFilterStrategy = if (onlyOrphansInHome) {
RoomListViewModel.SpaceFilterStrategy.ORPHANS_IF_SPACE_NULL
} else {
RoomListViewModel.SpaceFilterStrategy.ALL_IF_SPACE_NULL
}
) {
it.memberships = listOf(Membership.JOIN)
it.roomCategoryFilter = RoomCategoryFilter.ONLY_WITH_NOTIFICATIONS
}
} }
} }
@ -332,6 +280,67 @@ class RoomListSectionBuilderSpace(
} }
} }
private fun buildNotificationsSection(sections: MutableList<RoomsSection>, activeSpaceAwareQueries: MutableList<RoomListViewModel.ActiveSpaceQueryUpdater>) {
if (autoAcceptInvites.showInvites()) {
addSection(
sections = sections,
activeSpaceUpdaters = activeSpaceAwareQueries,
nameRes = R.string.invitations_header,
notifyOfLocalEcho = true,
spaceFilterStrategy = if (onlyOrphansInHome) {
RoomListViewModel.SpaceFilterStrategy.ORPHANS_IF_SPACE_NULL
} else {
RoomListViewModel.SpaceFilterStrategy.ALL_IF_SPACE_NULL
},
countRoomAsNotif = true
) {
it.memberships = listOf(Membership.INVITE)
it.roomCategoryFilter = RoomCategoryFilter.ALL
}
}
addSection(
sections = sections,
activeSpaceUpdaters = activeSpaceAwareQueries,
nameRes = R.string.bottom_action_rooms,
notifyOfLocalEcho = false,
spaceFilterStrategy = if (onlyOrphansInHome) {
RoomListViewModel.SpaceFilterStrategy.ORPHANS_IF_SPACE_NULL
} else {
RoomListViewModel.SpaceFilterStrategy.ALL_IF_SPACE_NULL
}
) {
it.memberships = listOf(Membership.JOIN)
it.roomCategoryFilter = RoomCategoryFilter.ONLY_WITH_NOTIFICATIONS
}
}
private fun buildFilteredSection(sections: MutableList<RoomsSection>) {
// Used when searching for rooms
withQueryParams(
{
it.memberships = Membership.activeMemberships()
},
{ qpm ->
val name = stringProvider.getString(R.string.bottom_action_rooms)
val updatableFilterLivePageResult = session.getFilteredPagedRoomSummariesLive(qpm)
onUpdatable(updatableFilterLivePageResult)
val itemCountFlow = updatableFilterLivePageResult.livePagedList.asFlow()
.flatMapLatest { session.getRoomCountLive(updatableFilterLivePageResult.queryParams).asFlow() }
.distinctUntilChanged()
sections.add(
RoomsSection(
sectionName = name,
livePages = updatableFilterLivePageResult.livePagedList,
itemCount = itemCountFlow
)
)
}
)
}
private fun addSection(sections: MutableList<RoomsSection>, private fun addSection(sections: MutableList<RoomsSection>,
activeSpaceUpdaters: MutableList<RoomListViewModel.ActiveSpaceQueryUpdater>, activeSpaceUpdaters: MutableList<RoomListViewModel.ActiveSpaceQueryUpdater>,
@StringRes nameRes: Int, @StringRes nameRes: Int,
@ -339,83 +348,82 @@ class RoomListSectionBuilderSpace(
spaceFilterStrategy: RoomListViewModel.SpaceFilterStrategy = RoomListViewModel.SpaceFilterStrategy.NONE, spaceFilterStrategy: RoomListViewModel.SpaceFilterStrategy = RoomListViewModel.SpaceFilterStrategy.NONE,
countRoomAsNotif: Boolean = false, countRoomAsNotif: Boolean = false,
query: (RoomSummaryQueryParams.Builder) -> Unit) { query: (RoomSummaryQueryParams.Builder) -> Unit) {
withQueryParams( withQueryParams(query) { roomQueryParams ->
{ query.invoke(it) }, val updatedQueryParams = roomQueryParams.process(spaceFilterStrategy, appStateHandler.safeActiveSpaceId())
{ roomQueryParams -> val liveQueryParams = MutableStateFlow(updatedQueryParams)
val name = stringProvider.getString(nameRes) val itemCountFlow = liveQueryParams
session.getFilteredPagedRoomSummariesLive( .flatMapLatest {
roomQueryParams.process(spaceFilterStrategy, appStateHandler.safeActiveSpaceId()), session.getRoomCountLive(it).asFlow()
pagedListConfig }
).also { .flowOn(Dispatchers.Main)
when (spaceFilterStrategy) { .distinctUntilChanged()
RoomListViewModel.SpaceFilterStrategy.ORPHANS_IF_SPACE_NULL -> {
activeSpaceUpdaters.add(object : RoomListViewModel.ActiveSpaceQueryUpdater { val name = stringProvider.getString(nameRes)
override fun updateForSpaceId(roomId: String?) { val filteredPagedRoomSummariesLive = session.getFilteredPagedRoomSummariesLive(
it.queryParams = roomQueryParams.copy( roomQueryParams.process(spaceFilterStrategy, appStateHandler.safeActiveSpaceId()),
activeSpaceFilter = ActiveSpaceFilter.ActiveSpace(roomId) pagedListConfig
) )
} when (spaceFilterStrategy) {
}) RoomListViewModel.SpaceFilterStrategy.ORPHANS_IF_SPACE_NULL -> {
} activeSpaceUpdaters.add(object : RoomListViewModel.ActiveSpaceQueryUpdater {
RoomListViewModel.SpaceFilterStrategy.ALL_IF_SPACE_NULL -> { override fun updateForSpaceId(roomId: String?) {
activeSpaceUpdaters.add(object : RoomListViewModel.ActiveSpaceQueryUpdater { filteredPagedRoomSummariesLive.queryParams = roomQueryParams.copy(
override fun updateForSpaceId(roomId: String?) { activeSpaceFilter = ActiveSpaceFilter.ActiveSpace(roomId)
if (roomId != null) { )
it.queryParams = roomQueryParams.copy( liveQueryParams.update { filteredPagedRoomSummariesLive.queryParams }
activeSpaceFilter = ActiveSpaceFilter.ActiveSpace(roomId)
)
} else {
it.queryParams = roomQueryParams.copy(
activeSpaceFilter = ActiveSpaceFilter.None
)
}
}
})
}
RoomListViewModel.SpaceFilterStrategy.NONE -> {
// we ignore current space for this one
}
} }
}.livePagedList })
.let { livePagedList -> }
// use it also as a source to update count RoomListViewModel.SpaceFilterStrategy.ALL_IF_SPACE_NULL -> {
livePagedList.asFlow() activeSpaceUpdaters.add(object : RoomListViewModel.ActiveSpaceQueryUpdater {
.onEach { override fun updateForSpaceId(roomId: String?) {
Timber.v("Thread space list: ${Thread.currentThread()}") if (roomId != null) {
sections.find { it.sectionName == name } filteredPagedRoomSummariesLive.queryParams = roomQueryParams.copy(
?.notificationCount activeSpaceFilter = ActiveSpaceFilter.ActiveSpace(roomId)
?.postValue( )
if (countRoomAsNotif) { } else {
RoomAggregateNotificationCount(it.size, it.size) filteredPagedRoomSummariesLive.queryParams = roomQueryParams.copy(
} else { activeSpaceFilter = ActiveSpaceFilter.None
session.getNotificationCountForRooms(
roomQueryParams.process(spaceFilterStrategy, appStateHandler.safeActiveSpaceId())
)
}
)
}
.flowOn(Dispatchers.Default)
.launchIn(viewModelScope)
val itemCountFlow = livePagedList.asFlow()
.flatMapLatest {
val queryParams = roomQueryParams.process(spaceFilterStrategy, appStateHandler.safeActiveSpaceId())
session.getRoomCountLive(queryParams).asFlow()
}
.distinctUntilChanged()
sections.add(
RoomsSection(
sectionName = name,
livePages = livePagedList,
notifyOfLocalEcho = notifyOfLocalEcho,
itemCount = itemCountFlow
)
) )
} }
liveQueryParams.update { filteredPagedRoomSummariesLive.queryParams }
}
})
} }
RoomListViewModel.SpaceFilterStrategy.NONE -> {
// we ignore current space for this one
}
}
) val livePagedList = filteredPagedRoomSummariesLive.livePagedList
// use it also as a source to update count
livePagedList.asFlow()
.onEach {
Timber.v("Thread space list: ${Thread.currentThread()}")
sections.find { it.sectionName == name }
?.notificationCount
?.postValue(
if (countRoomAsNotif) {
RoomAggregateNotificationCount(it.size, it.size)
} else {
session.getNotificationCountForRooms(
roomQueryParams.process(spaceFilterStrategy, appStateHandler.safeActiveSpaceId())
)
}
)
}
.flowOn(Dispatchers.Default)
.launchIn(viewModelScope)
sections.add(
RoomsSection(
sectionName = name,
livePages = livePagedList,
notifyOfLocalEcho = notifyOfLocalEcho,
itemCount = itemCountFlow
)
)
}
} }
private fun withQueryParams(builder: (RoomSummaryQueryParams.Builder) -> Unit, block: (RoomSummaryQueryParams) -> Unit) { private fun withQueryParams(builder: (RoomSummaryQueryParams.Builder) -> Unit, block: (RoomSummaryQueryParams) -> Unit) {